diff --git a/app/models/tag_rule/filter_products.rb b/app/models/tag_rule/filter_products.rb new file mode 100644 index 0000000000..e087d8737a --- /dev/null +++ b/app/models/tag_rule/filter_products.rb @@ -0,0 +1,37 @@ +class TagRule::FilterProducts < TagRule + preference :matched_variants_visibility, :string, default: "visible" + preference :variant_tags, :string, default: "" + + attr_accessible :preferred_matched_variants_visibility, :preferred_variant_tags + + private + + # Warning: this should only EVER be called via TagRule#apply + def apply! + unless preferred_matched_variants_visibility == "visible" + subject.reject! do |product| + product[:variants].reject!{ |v| tags_match?(v) } + product[:variants].empty? + end + end + end + + def apply_default! + if preferred_matched_variants_visibility == "visible" + subject.reject! do |product| + product[:variants].reject!{ |v| tags_match?(v) } + product[:variants].empty? + end + end + end + + def tags_match?(variant) + variant_tags = variant.andand[:tag_list] || [] + preferred_tags = preferred_variant_tags.split(",") + ( variant_tags & preferred_tags ).any? + end + + def subject_class_matches? + subject.class == HashWithIndifferentAccess + end +end diff --git a/spec/factories.rb b/spec/factories.rb index b4a3a1b573..2e29e74316 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -290,6 +290,10 @@ FactoryGirl.define do enterprise { FactoryGirl.create :distributor_enterprise } end + factory :filter_products_tag_rule, class: TagRule::FilterProducts do + enterprise { FactoryGirl.create :distributor_enterprise } + end + factory :tag_rule, class: TagRule::DiscountOrder do enterprise { FactoryGirl.create :distributor_enterprise } before(:create) do |tr| diff --git a/spec/models/tag_rule/filter_products_spec.rb b/spec/models/tag_rule/filter_products_spec.rb new file mode 100644 index 0000000000..2f1d9ec495 --- /dev/null +++ b/spec/models/tag_rule/filter_products_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +describe TagRule::FilterProducts, type: :model do + let!(:tag_rule) { create(:filter_products_tag_rule) } + + describe "determining whether tags match for a given variant" do + context "when the variantm is nil" do + + it "returns false" do + expect(tag_rule.send(:tags_match?, nil)).to be false + end + end + + context "when the variant is not nil" do + let(:variant_object) { { tag_list: ["member","local","volunteer"] } } + + context "when the rule has no preferred variant tags specified" do + before { allow(tag_rule).to receive(:preferred_variant_tags) { "" } } + it { expect(tag_rule.send(:tags_match?, variant_object)).to be false } + end + + context "when the rule has preferred variant tags specified that match ANY of the variant tags" do + before { allow(tag_rule).to receive(:preferred_variant_tags) { "wholesale,some_tag,member" } } + it { expect(tag_rule.send(:tags_match?, variant_object)).to be true } + end + + context "when the rule has preferred variant tags specified that match NONE of the variant tags" do + before { allow(tag_rule).to receive(:preferred_variant_tags) { "wholesale,some_tag,some_other_tag" } } + it { expect(tag_rule.send(:tags_match?, variant_object)).to be false } + end + end + end + + describe "applying the rule" do + # Assume that all validation is done by the TagRule base class + + let(:product1) { { name: "product1", variants: [{ name: "v1", tag_list: ["tag1", "something", "somethingelse"]}] } } + let(:product2) { { name: "product2", variants: [{ name: "v2", tag_list: ["tag2"]}] } } + let(:product3) { { name: "product3", variants: [{ name: "v3", tag_list: ["tag3"]}] } } + let!(:product_hash) { [product1, product2, product3] } + + before do + tag_rule.update_attribute(:preferred_variant_tags, "tag2") + tag_rule.set_context(product_hash, nil) + end + + context "apply!" do + context "when showing matching variants" do + before { tag_rule.update_attribute(:preferred_matched_variants_visibility, "visible") } + it "does nothing" do + tag_rule.send(:apply!) + expect(product_hash).to eq [product1, product2, product3] + end + end + + context "when hiding matching variants" do + before { tag_rule.update_attribute(:preferred_matched_variants_visibility, "hidden") } + it "removes matching variants from the list" do + tag_rule.send(:apply!) + expect(product_hash).to eq [product1, product3] + end + end + end + + context "apply_default!" do + context "when showing matching variants" do + before { tag_rule.update_attribute(:preferred_matched_variants_visibility, "visible") } + it "remove matching variants from the list" do + tag_rule.send(:apply_default!) + expect(product_hash).to eq [product1, product3] + end + end + + context "when hiding matching variants" do + before { tag_rule.update_attribute(:preferred_matched_variants_visibility, "hidden") } + it "does nothing" do + tag_rule.send(:apply_default!) + expect(product_hash).to eq [product1, product2, product3] + end + end + end + end +end diff --git a/spec/models/tag_rule/filter_shipping_methods_spec.rb b/spec/models/tag_rule/filter_shipping_methods_spec.rb index 539aa3c6ca..ae05478587 100644 --- a/spec/models/tag_rule/filter_shipping_methods_spec.rb +++ b/spec/models/tag_rule/filter_shipping_methods_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe TagRule::DiscountOrder, type: :model do +describe TagRule::FilterShippingMethods, type: :model do let!(:tag_rule) { create(:filter_shipping_methods_tag_rule) } describe "determining whether tags match for a given shipping method" do