require 'spec_helper' describe Enterprise do include AuthenticationWorkflow describe "sending emails" do describe "on creation" do let!(:user) { create_enterprise_user( enterprise_limit: 2 ) } let!(:enterprise) { create(:enterprise, owner: user) } it "sends a welcome email" do expect do create(:enterprise, owner: user) end.to enqueue_job WelcomeEnterpriseJob end end end describe "associations" do it { should belong_to(:owner) } it { should have_many(:supplied_products) } it { should have_many(:distributed_orders) } it { should belong_to(:address) } it { should have_many(:product_distributions) } it "destroys enterprise roles upon its own demise" do e = create(:enterprise) u = create(:user) u.enterprise_roles.build(enterprise: e).save! role = e.enterprise_roles.first e.destroy EnterpriseRole.where(id: role.id).should be_empty end it "destroys supplied products upon destroy" do s = create(:supplier_enterprise) p = create(:simple_product, supplier: s) s.destroy Spree::Product.where(id: p.id).should be_empty end it "destroys relationships upon destroy" do e = create(:enterprise) e_other = create(:enterprise) er1 = create(:enterprise_relationship, parent: e, child: e_other) er2 = create(:enterprise_relationship, child: e, parent: e_other) e.destroy EnterpriseRelationship.where(id: [er1, er2]).should be_empty end describe "relationships to other enterprises" do let(:e) { create(:distributor_enterprise) } let(:p) { create(:supplier_enterprise) } let(:c) { create(:distributor_enterprise) } let!(:er1) { create(:enterprise_relationship, parent_id: p.id, child_id: e.id) } let!(:er2) { create(:enterprise_relationship, parent_id: e.id, child_id: c.id) } it "finds relatives" do e.relatives.should match_array [p, c] end it "finds relatives_including_self" do expect(e.relatives_including_self).to include e end it "scopes relatives to visible distributors" do e.should_receive(:relatives_including_self).and_return(relatives = []) relatives.should_receive(:is_distributor).and_return relatives e.distributors end it "scopes relatives to visible producers" do e.should_receive(:relatives_including_self).and_return(relatives = []) relatives.should_receive(:is_primary_producer).and_return relatives e.suppliers end end describe "ownership" do let(:u1) { create_enterprise_user } let(:u2) { create_enterprise_user } let!(:e) { create(:enterprise, owner: u1 ) } it "adds new owner to list of managers" do expect(e.owner).to eq u1 expect(e.users).to include u1 expect(e.users).to_not include u2 e.owner = u2 e.save! e.reload expect(e.owner).to eq u2 expect(e.users).to include u1, u2 end it "validates ownership limit" do expect(u1.enterprise_limit).to be 5 expect(u1.owned_enterprises(:reload)).to eq [e] 4.times { create(:enterprise, owner: u1) } e2 = create(:enterprise, owner: u2) expect { e2.owner = u1 e2.save! }.to raise_error ActiveRecord::RecordInvalid, "Validation failed: #{u1.email} is not permitted to own any more enterprises (limit is 5)." end end end describe "validations" do subject { FactoryBot.create(:distributor_enterprise) } it { should validate_presence_of(:name) } it { should validate_uniqueness_of(:permalink) } it { should ensure_length_of(:description).is_at_most(255) } it "requires an owner" do expect{ e = create(:enterprise, owner: nil) }.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Owner can't be blank" end describe "name uniqueness" do let(:owner) { create(:user, email: 'owner@example.com') } let!(:enterprise) { create(:enterprise, name: 'Enterprise', owner: owner) } it "prevents duplicate names for new records" do e = Enterprise.new name: enterprise.name expect(e).to_not be_valid expect(e.errors[:name].first).to include I18n.t('enterprise_name_error', email: owner.email) end it "prevents duplicate names for existing records" do e = create(:enterprise, name: 'foo') e.name = enterprise.name expect(e).to_not be_valid expect(e.errors[:name].first).to include I18n.t('enterprise_name_error', email: owner.email) end it "does not prohibit the saving of an enterprise with no name clash" do enterprise.should be_valid end it "sets the enterprise contact to the owner by default" do enterprise.contact.should eq enterprise.owner end context "prevent an wrong instagram link pattern" do it "expects to be invalid the instagram attribute @my-user" do e = build(:enterprise, instagram: '@my-user') expect(e).to_not be_valid end it "expects to be invalid the instagram attribute https://facebook.com/user" do e = build(:enterprise, instagram: 'https://facebook.com/user') expect(e).to_not be_valid end it "expects to be invalid the instagram attribute tagram.com/user" do e = build(:enterprise, instagram: 'tagram.com/user') expect(e).to_not be_valid end it "expects to be invalid the instagram attribute https://instagram.com/user/preferences" do e = build(:enterprise, instagram: 'https://instagram.com/user/preferences') expect(e).to_not be_valid end end context "accepted pattern" do it "expects to be valid empty instagram attribute" do e = build(:enterprise) expect(e).to be_valid end it "expects be valid the instagram attribute @user" do e = build(:enterprise, instagram: '@user') expect(e).to be_valid end it "expects be valid the instagram attribute @my_www5.example" do e = build(:enterprise, instagram: '@my_www5.example') expect(e).to be_valid end it "expects be valid the instagram attribute http://instagram.com/user" do e = build(:enterprise, instagram: 'http://instagram.com/user') expect(e).to be_valid end it "expects be valid the instagram attribute https://instagram.com/user/" do e = build(:enterprise, instagram: 'https://instagram.com/user/') expect(e).to be_valid end it "expects be valid the instagram attribute https://www.instagram.com/user" do e = build(:enterprise, instagram: 'https://www.instagram.com/user') expect(e).to be_valid end it "expects be valid the instagram attribute instagram.com/user" do e = build(:enterprise, instagram: 'instagram.com/user') expect(e).to be_valid end it "renders the expected pattern" do e = build(:enterprise, instagram: 'instagram.com/user') expect(e.instagram).to eq('@user') end end end describe "preferred_shopfront_taxon_order" do it "empty strings are valid" do enterprise = build(:enterprise, preferred_shopfront_taxon_order: "") expect(enterprise).to be_valid end it "a single integer is valid" do enterprise = build(:enterprise, preferred_shopfront_taxon_order: "11") expect(enterprise).to be_valid end it "comma delimited integers are valid" do enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,2,3") expect(enterprise).to be_valid enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,22,333") expect(enterprise).to be_valid end it "commas at the beginning and end are disallowed" do enterprise = build(:enterprise, preferred_shopfront_taxon_order: ",1,2,3") expect(enterprise).to be_invalid enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,2,3,") expect(enterprise).to be_invalid end it "any other characters are invalid" do enterprise = build(:enterprise, preferred_shopfront_taxon_order: "a1,2,3") expect(enterprise).to be_invalid enterprise = build(:enterprise, preferred_shopfront_taxon_order: ".1,2,3") expect(enterprise).to be_invalid enterprise = build(:enterprise, preferred_shopfront_taxon_order: " 1,2,3") expect(enterprise).to be_invalid end end end describe "delegations" do #subject { FactoryBot.create(:distributor_enterprise, :address => FactoryBot.create(:address)) } it { should delegate(:latitude).to(:address) } it { should delegate(:longitude).to(:address) } it { should delegate(:city).to(:address) } it { should delegate(:state_name).to(:address) } end describe "callbacks" do it "restores permalink to original value when it is changed and invalid" do e1 = create(:enterprise, permalink: "taken") e2 = create(:enterprise, permalink: "not_taken") e2.permalink = "taken" e2.save expect(e2.permalink).to eq "not_taken" end end describe "scopes" do describe 'visible' do it 'find visible enterprises' do d1 = create(:distributor_enterprise, visible: false) s1 = create(:supplier_enterprise) Enterprise.visible.should == [s1] end end describe "activated" do let!(:unconfirmed_user) { create(:user, confirmed_at: nil, enterprise_limit: 2) } let!(:inactive_enterprise) { create(:enterprise, sells: "unspecified") } let!(:active_enterprise) { create(:enterprise, sells: "none") } it "finds enterprises that have a sells property other than 'unspecified'" do activated_enterprises = Enterprise.activated expect(activated_enterprises).to include active_enterprise expect(activated_enterprises).to_not include inactive_enterprise end end describe "ready_for_checkout" do let!(:e) { create(:enterprise) } it "does not show enterprises with no payment methods" do create(:shipping_method, distributors: [e]) Enterprise.ready_for_checkout.should_not include e end it "does not show enterprises with no shipping methods" do create(:payment_method, distributors: [e]) Enterprise.ready_for_checkout.should_not include e end it "does not show enterprises with unavailable payment methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e], active: false) Enterprise.ready_for_checkout.should_not include e end it "shows enterprises with available payment and shipping methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e]) Enterprise.ready_for_checkout.should include e end end describe "not_ready_for_checkout" do let!(:e) { create(:enterprise) } it "shows enterprises with no payment methods" do create(:shipping_method, distributors: [e]) Enterprise.not_ready_for_checkout.should include e end it "shows enterprises with no shipping methods" do create(:payment_method, distributors: [e]) Enterprise.not_ready_for_checkout.should include e end it "shows enterprises with unavailable payment methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e], active: false) Enterprise.not_ready_for_checkout.should include e end it "does not show enterprises with available payment and shipping methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e]) Enterprise.not_ready_for_checkout.should_not include e end end describe "#ready_for_checkout?" do let!(:e) { create(:enterprise) } it "returns false for enterprises with no payment methods" do create(:shipping_method, distributors: [e]) e.reload.should_not be_ready_for_checkout end it "returns false for enterprises with no shipping methods" do create(:payment_method, distributors: [e]) e.reload.should_not be_ready_for_checkout end it "returns false for enterprises with unavailable payment methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e], active: false) e.reload.should_not be_ready_for_checkout end it "returns true for enterprises with available payment and shipping methods" do create(:shipping_method, distributors: [e]) create(:payment_method, distributors: [e]) e.reload.should be_ready_for_checkout end end describe "distributors_with_active_order_cycles" do it "finds active distributors by order cycles" do s = create(:supplier_enterprise) d = create(:distributor_enterprise) p = create(:product) create(:simple_order_cycle, suppliers: [s], distributors: [d], variants: [p.master]) Enterprise.distributors_with_active_order_cycles.should == [d] end it "should not find inactive distributors by order cycles" do s = create(:supplier_enterprise) d = create(:distributor_enterprise) p = create(:product) create(:simple_order_cycle, :orders_open_at => 10.days.from_now, orders_close_at: 17.days.from_now, suppliers: [s], distributors: [d], variants: [p.master]) Enterprise.distributors_with_active_order_cycles.should_not include d end end describe "supplying_variant_in" do it "finds producers by supply of master variant" do s = create(:supplier_enterprise) p = create(:simple_product, supplier: s) Enterprise.supplying_variant_in([p.master]).should == [s] end it "finds producers by supply of variant" do s = create(:supplier_enterprise) p = create(:simple_product, supplier: s) v = create(:variant, product: p) Enterprise.supplying_variant_in([v]).should == [s] end it "returns multiple enterprises when given multiple variants" do s1 = create(:supplier_enterprise) s2 = create(:supplier_enterprise) p1 = create(:simple_product, supplier: s1) p2 = create(:simple_product, supplier: s2) Enterprise.supplying_variant_in([p1.master, p2.master]).should match_array [s1, s2] end it "does not return duplicates" do s = create(:supplier_enterprise) p1 = create(:simple_product, supplier: s) p2 = create(:simple_product, supplier: s) Enterprise.supplying_variant_in([p1.master, p2.master]).should == [s] end end describe "distributing_products" do it "returns enterprises distributing via a product distribution" do d = create(:distributor_enterprise) p = create(:product, distributors: [d]) Enterprise.distributing_products(p).should == [d] end it "returns enterprises distributing via an order cycle" do d = create(:distributor_enterprise) p = create(:product) oc = create(:simple_order_cycle, distributors: [d], variants: [p.master]) Enterprise.distributing_products(p).should == [d] end it "returns enterprises distributing via a product distribution" do d = create(:distributor_enterprise) p = create(:product, distributors: [d]) Enterprise.distributing_products([p]).should == [d] end it "returns enterprises distributing via an order cycle" do d = create(:distributor_enterprise) p = create(:product) oc = create(:simple_order_cycle, distributors: [d], variants: [p.master]) Enterprise.distributing_products([p]).should == [d] end it "does not return duplicate enterprises" do d = create(:distributor_enterprise) p1 = create(:product, distributors: [d]) p2 = create(:product, distributors: [d]) Enterprise.distributing_products([p1, p2]).should == [d] end end describe "managed_by" do it "shows only enterprises for given user" do user = create(:user) user.spree_roles = [] e1 = create(:enterprise) e2 = create(:enterprise) e1.enterprise_roles.build(user: user).save enterprises = Enterprise.managed_by user enterprises.count.should == 1 enterprises.should include e1 end it "shows all enterprises for admin user" do user = create(:admin_user) e1 = create(:enterprise) e2 = create(:enterprise) enterprises = Enterprise.managed_by user enterprises.count.should == 2 enterprises.should include e1 enterprises.should include e2 end end end describe "callbacks" do describe "after creation" do let(:owner) { create(:user, enterprise_limit: 10) } let(:hub1) { create(:distributor_enterprise, owner: owner) } let(:hub2) { create(:distributor_enterprise, owner: owner) } let(:hub3) { create(:distributor_enterprise, owner: owner) } let(:producer1) { create(:supplier_enterprise, owner: owner) } let(:producer2) { create(:supplier_enterprise, owner: owner) } describe "when a producer is created" do before do hub1 hub2 end it "creates links from the new producer to all hubs owned by the same user, granting add_to_order_cycle and create_variant_overrides permissions" do producer1 should_have_enterprise_relationship from: producer1, to: hub1, with: [:add_to_order_cycle, :create_variant_overrides] should_have_enterprise_relationship from: producer1, to: hub2, with: [:add_to_order_cycle, :create_variant_overrides] end it "does not create any other links" do expect do producer1 end.to change(EnterpriseRelationship, :count).by(2) end end describe "when a new hub is created" do it "it creates links to the hub, from all producers owned by the same user, granting add_to_order_cycle and create_variant_overrides permissions" do producer1 producer2 hub1 should_have_enterprise_relationship from: producer1, to: hub1, with: [:add_to_order_cycle, :create_variant_overrides] should_have_enterprise_relationship from: producer2, to: hub1, with: [:add_to_order_cycle, :create_variant_overrides] end it "creates links from the new hub to all hubs owned by the same user, granting add_to_order_cycle permission" do hub1 hub2 hub3 should_have_enterprise_relationship from: hub2, to: hub1, with: [:add_to_order_cycle] should_have_enterprise_relationship from: hub3, to: hub1, with: [:add_to_order_cycle] should_have_enterprise_relationship from: hub3, to: hub2, with: [:add_to_order_cycle] end it "does not create any other links" do producer1 producer2 expect { hub1 }.to change(EnterpriseRelationship, :count).by(2) # 2 producer links expect { hub2 }.to change(EnterpriseRelationship, :count).by(3) # 2 producer links + 1 hub link expect { hub3 }.to change(EnterpriseRelationship, :count).by(4) # 2 producer links + 2 hub links end end def should_have_enterprise_relationship(opts={}) er = EnterpriseRelationship.where(parent_id: opts[:from], child_id: opts[:to]).last er.should_not be_nil if opts[:with] == :all_permissions er.permissions.map(&:name).should match_array ['add_to_order_cycle', 'manage_products', 'edit_profile', 'create_variant_overrides'] elsif opts.key? :with er.permissions.map(&:name).should match_array opts[:with].map(&:to_s) end end end end describe "finding variants distributed by the enterprise" do it "finds master and other variants" do d = create(:distributor_enterprise) p = create(:product, distributors: [d]) v = p.variants.first d.distributed_variants.should match_array [p.master, v] end pending "finds variants distributed by order cycle" do # there isn't actually a method for this on Enterprise? d = create(:distributor_enterprise) p = create(:product) v = p.variants.first oc = create(:simple_order_cycle, distributors: [d], variants: [v]) # This method doesn't do what this test says it does... d.distributed_variants.should match_array [v] end end describe "finding variants distributed by the enterprise in a product distribution only" do it "finds master and other variants" do d = create(:distributor_enterprise) p = create(:product, distributors: [d]) v = p.variants.first d.product_distribution_variants.should match_array [p.master, v] end it "does not find variants distributed by order cycle" do d = create(:distributor_enterprise) p = create(:product) v = p.variants.first oc = create(:simple_order_cycle, distributors: [d], variants: [v]) d.product_distribution_variants.should == [] end end describe "taxons" do let(:distributor) { create(:distributor_enterprise) } let(:supplier) { create(:supplier_enterprise) } let(:taxon1) { create(:taxon) } let(:taxon2) { create(:taxon) } let(:product1) { create(:simple_product, primary_taxon: taxon1, taxons: [taxon1]) } let(:product2) { create(:simple_product, primary_taxon: taxon1, taxons: [taxon1, taxon2]) } it "gets all taxons of all distributed products" do Spree::Product.stub(:in_distributor).and_return [product1, product2] distributor.distributed_taxons.should match_array [taxon1, taxon2] end it "gets all taxons of all supplied products" do Spree::Product.stub(:in_supplier).and_return [product1, product2] supplier.supplied_taxons.should match_array [taxon1, taxon2] end end describe "presentation of attributes" do let(:distributor) { create(:distributor_enterprise, website: "http://www.google.com", facebook: "www.facebook.com/roger", linkedin: "https://linkedin.com") } it "strips http from url fields" do distributor.website.should == "www.google.com" distributor.facebook.should == "www.facebook.com/roger" distributor.linkedin.should == "linkedin.com" end end describe "producer properties" do let(:supplier) { create(:supplier_enterprise) } it "sets producer properties" do supplier.set_producer_property 'Organic Certified', 'NASAA 12345' supplier.producer_properties.count.should == 1 supplier.producer_properties.first.value.should == 'NASAA 12345' supplier.producer_properties.first.property.presentation.should == 'Organic Certified' end end describe "provide enterprise category" do let(:producer_sell_all) { build(:enterprise, is_primary_producer: true, sells: "any") } let(:producer_sell_own) { build(:enterprise, is_primary_producer: true, sells: "own") } let(:producer_sell_none) { build(:enterprise, is_primary_producer: true, sells: "none") } let(:non_producer_sell_all) { build(:enterprise, is_primary_producer: false, sells: "any") } let(:non_producer_sell_own) { build(:enterprise, is_primary_producer: false, sells: "own") } let(:non_producer_sell_none) { build(:enterprise, is_primary_producer: false, sells: "none") } it "should output enterprise categories" do producer_sell_all.is_primary_producer.should == true producer_sell_all.sells.should == "any" producer_sell_all.category.should == :producer_hub producer_sell_own.category.should == :producer_shop producer_sell_none.category.should == :producer non_producer_sell_all.category.should == :hub non_producer_sell_own.category.should == :hub non_producer_sell_none.category.should == :hub_profile end end describe "finding and automatically assigning a permalink" do let(:enterprise) { build(:enterprise, name: "Name To Turn Into A Permalink") } it "assigns permalink when initialized" do allow(Enterprise).to receive(:find_available_permalink).and_return("available_permalink") Enterprise.should_receive(:find_available_permalink).with("Name To Turn Into A Permalink") expect( lambda { enterprise.send(:initialize_permalink) } ).to change{ enterprise.permalink }.to( "available_permalink" ) end describe "finding a permalink" do let!(:enterprise1) { create(:enterprise, permalink: "permalink") } let!(:enterprise2) { create(:enterprise, permalink: "permalink1") } it "parameterizes the value provided" do expect(Enterprise.find_available_permalink("Some Unused Permalink")).to eq "some-unused-permalink" end it "sets the permalink to 'my-enterprise' if parametized permalink is blank" do expect(Enterprise.find_available_permalink("")).to eq "my-enterprise" expect(Enterprise.find_available_permalink("$$%{$**}$%}")).to eq "my-enterprise" end it "finds and index value based on existing permalinks" do expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2" end it "ignores permalinks with characters after the index value" do create(:enterprise, permalink: "permalink2xxx") expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2" end it "finds available permalink similar to existing" do create(:enterprise, permalink: "permalink2xxx") expect(Enterprise.find_available_permalink("permalink2")).to eq "permalink2" end it "finds gaps in the indices of existing permalinks" do create(:enterprise, permalink: "permalink3") expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2" end end end end