diff --git a/.circleci/config.yml b/.circleci/config.yml index 7031e874..fe9e8227 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,31 +1,71 @@ version: 2.1 orbs: + # Required for feature specs. + browser-tools: circleci/browser-tools@1.1 + # Always take the latest version of the orb, this allows us to # run specs against Solidus supported versions only without the need # to change this configuration every time a Solidus version is released # or goes EOL. solidusio_extensions: solidusio/extensions@volatile +commands: + test-with-starter-frontend: + steps: + - checkout + - browser-tools/install-chrome + - run: + name: Install libvips + command: | + sudo apt-get update + sudo apt-get install -yq libvips-dev + - solidusio_extensions/test-branch: + branch: main + command: | + export FRONTEND=starter + sudo gem update --system + gem install bundler rails:'~>7.2' + bundle exec rake + - solidusio_extensions/store-test-results + jobs: run-specs-with-postgres: executor: name: solidusio_extensions/postgres - ruby_version: "3.0" + ruby_version: "3.2" steps: - - solidusio_extensions/run-tests + - test-with-starter-frontend + run-specs-with-mysql: executor: name: solidusio_extensions/mysql - ruby_version: "3.0" + ruby_version: "3.2" steps: - - solidusio_extensions/run-tests + - test-with-starter-frontend + + run-specs-with-sqlite: + executor: + name: solidusio_extensions/sqlite + ruby_version: "3.1" + steps: + - test-with-starter-frontend + + lint-code: + executor: + name: solidusio_extensions/sqlite-memory + ruby_version: "3.2" + steps: + - solidusio_extensions/lint-code workflows: "Run specs on supported Solidus versions": jobs: - run-specs-with-postgres - run-specs-with-mysql + - run-specs-with-sqlite + - lint-code + "Weekly run specs against master": triggers: - schedule: @@ -37,3 +77,4 @@ workflows: jobs: - run-specs-with-postgres - run-specs-with-mysql + - run-specs-with-sqlite diff --git a/.gitignore b/.gitignore index bcd4aea4..4b85c27d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ pkg *.swp spec/dummy spec/examples.txt +/sandbox +/dummy-app + diff --git a/.rubocop.yml b/.rubocop.yml index 6207a647..d6fbb9d9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,9 @@ +inherit_from: .rubocop_todo.yml + require: - solidus_dev_support/rubocop + +AllCops: + TargetRubyVersion: 3.0 + NewCops: disable + \ No newline at end of file diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..d00947fb --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,154 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2025-01-22 08:20:44 UTC using RuboCop version 1.70.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# Configuration parameters: Severity, Include. +# Include: **/*.gemspec +Gemspec/RequiredRubyVersion: + Exclude: + - 'solidus_multi_domain.gemspec' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'app/decorators/controllers/solidus_multi_domain/taxons_controller_decorator.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Exclude: + - 'lib/generators/solidus_multi_domain/install/templates/sample_data/taxonomies.rb' + +# Offense count: 2 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 3 +Naming/AccessorMethodName: + Exclude: + - 'app/decorators/helpers/solidus_multi_domain/spree/products_helper_decorator.rb' + - 'app/models/spree/search/multi_domain.rb' + - 'lib/solidus_multi_domain/multi_domain_helpers.rb' + +# Offense count: 5 +# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. +# SupportedStyles: snake_case, normalcase, non_integer +# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 +Naming/VariableNumber: + Exclude: + - 'spec/controllers/products_controller_spec.rb' + - 'spec/models/spree/store_spec.rb' + - 'spec/requests/spree/api/products_controller_spec.rb' + +# Offense count: 2 +RSpec/BeforeAfterAll: + Exclude: + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 8 +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Exclude: + - 'spec/controllers/spree/api/line_items_controller_spec.rb' + - 'spec/controllers/spree/api/shipments_controller_spec.rb' + - 'spec/models/spree/line_item_spec.rb' + - 'spec/models/spree/taxon_decorator_spec.rb' + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 3 +# Configuration parameters: IgnoredMetadata. +RSpec/DescribeClass: + Exclude: + - 'spec/lib/spree_multi_domain/testing_support/factory_overrides_spec.rb' + - 'spec/requests/global_controller_helpers_spec.rb' + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 1 +RSpec/DescribeSymbol: + Exclude: + - 'spec/requests/spree/api/products_controller_spec.rb' + +# Offense count: 15 +# Configuration parameters: AssignmentOnly. +RSpec/InstanceVariable: + Exclude: + - 'spec/controllers/spree/admin/products_controller_spec.rb' + - 'spec/models/spree/product_spec.rb' + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 2 +RSpec/LeakyConstantDeclaration: + Exclude: + - 'spec/requests/template_renderer_spec.rb' + +# Offense count: 4 +RSpec/LetSetup: + Exclude: + - 'spec/controllers/products_controller_spec.rb' + - 'spec/requests/global_controller_helpers_spec.rb' + +# Offense count: 7 +RSpec/MultipleExpectations: + Max: 4 + +# Offense count: 4 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 6 + +# Offense count: 10 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only +RSpec/NamedSubject: + Exclude: + - 'spec/controllers/spree/api/line_items_controller_spec.rb' + - 'spec/controllers/spree/api/shipments_controller_spec.rb' + - 'spec/models/spree/line_item_spec.rb' + - 'spec/requests/spree/api/products_controller_spec.rb' + +# Offense count: 4 +# Configuration parameters: AllowedGroups. +RSpec/NestedGroups: + Max: 4 + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Whitelist, AllowedMethods, AllowedReceivers. +# Whitelist: find_by_sql, find_by_token_for +# AllowedMethods: find_by_sql, find_by_token_for +# AllowedReceivers: Gem::Specification, page +Rails/DynamicFindBy: + Exclude: + - 'app/decorators/controllers/solidus_multi_domain/taxons_controller_decorator.rb' + +# Offense count: 1 +# Configuration parameters: Include. +# Include: app/controllers/**/*.rb, app/mailers/**/*.rb +Rails/LexicallyScopedActionFilter: + Exclude: + - 'app/controllers/concerns/solidus_multi_domain/show_product_support.rb' + +# Offense count: 1 +# Configuration parameters: ForbiddenMethods, AllowedMethods. +# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all +Rails/SkipsModelValidations: + Exclude: + - 'app/decorators/helpers/solidus_multi_domain/spree/core/controller_helpers/order_decorator.rb' + +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. +# URISchemes: http, https +Layout/LineLength: + Max: 339 diff --git a/Gemfile b/Gemfile index a0c29750..189fd4d5 100644 --- a/Gemfile +++ b/Gemfile @@ -6,20 +6,13 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } branch = ENV.fetch('SOLIDUS_BRANCH', 'main') gem 'solidus', github: 'solidusio/solidus', branch: branch -# The solidus_frontend gem has been pulled out since v3.2 -if branch >= 'v3.2' - gem 'solidus_frontend' -elsif branch == 'main' - gem 'solidus_frontend', github: 'solidusio/solidus_frontend', branch: branch -else - gem 'solidus_frontend', github: 'solidusio/solidus', branch: branch -end - # Needed to help Bundler figure out how to resolve dependencies, # otherwise it takes forever to resolve them. # See https://github.com/bundler/bundler/issues/6677 gem 'rails', '>0.a' +gem 'rubocop-rails-omakase' + # Provides basic authentication functionality for testing parts of your engine gem 'solidus_auth_devise' diff --git a/Rakefile b/Rakefile index c08aa468..079e7e91 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,12 @@ # frozen_string_literal: true +require "bundler/gem_tasks" require 'solidus_dev_support/rake_tasks' SolidusDevSupport::RakeTasks.install -task default: 'extension:specs' +task :default do + require 'bundler' + Bundler.with_unbundled_env do + sh 'bin/rspec' + end +end diff --git a/app/controllers/concerns/solidus_multi_domain/create_line_item_support.rb b/app/controllers/concerns/solidus_multi_domain/create_line_item_support.rb index 56f29beb..6106f43b 100644 --- a/app/controllers/concerns/solidus_multi_domain/create_line_item_support.rb +++ b/app/controllers/concerns/solidus_multi_domain/create_line_item_support.rb @@ -1,18 +1,21 @@ # frozen_string_literal: true -module SolidusMultiDomain::CreateLineItemSupport - extend ActiveSupport::Concern +module SolidusMultiDomain + module CreateLineItemSupport + extend ActiveSupport::Concern - included do - prepend(InstanceMethods) - rescue_from SolidusMultiDomain::ProductDoesNotBelongToStoreError, with: :product_does_not_belong_to_store - end + included do + prepend(InstanceMethods) + rescue_from SolidusMultiDomain::ProductDoesNotBelongToStoreError, with: :product_does_not_belong_to_store + end - module InstanceMethods - private + module InstanceMethods + private - def product_does_not_belong_to_store - render json: { message: I18n.t('spree.errors.products_from_different_stores_may_not_be_added_to_this_order') }, status: :unprocessable_entity + def product_does_not_belong_to_store + render json: { message: I18n.t('spree.errors.products_from_different_stores_may_not_be_added_to_this_order') }, + status: :unprocessable_entity + end end end end diff --git a/app/controllers/concerns/solidus_multi_domain/show_product_support.rb b/app/controllers/concerns/solidus_multi_domain/show_product_support.rb index d2d68ef0..d135545a 100644 --- a/app/controllers/concerns/solidus_multi_domain/show_product_support.rb +++ b/app/controllers/concerns/solidus_multi_domain/show_product_support.rb @@ -1,17 +1,19 @@ # frozen_string_literal: true -module SolidusMultiDomain::ShowProductSupport - extend ActiveSupport::Concern +module SolidusMultiDomain + module ShowProductSupport + extend ActiveSupport::Concern - included do - prepend(InstanceMethods) - before_action :can_show_product, only: :show - end + included do + prepend(InstanceMethods) + before_action :can_show_product, only: :show + end + + module InstanceMethods + def can_show_product + @product ||= Spree::Product.friendly.find(params[:id]) + return unless @product.stores.empty? || !@product.stores.include?(current_store) - module InstanceMethods - def can_show_product - @product ||= Spree::Product.friendly.find(params[:id]) - if @product.stores.empty? || !@product.stores.include?(current_store) raise ActiveRecord::RecordNotFound end end diff --git a/app/controllers/spree/admin/stores_controller.rb b/app/controllers/spree/admin/stores_controller.rb index f4106a59..7b09a3ca 100644 --- a/app/controllers/spree/admin/stores_controller.rb +++ b/app/controllers/spree/admin/stores_controller.rb @@ -1,26 +1,30 @@ # frozen_string_literal: true -class Spree::Admin::StoresController < Spree::Admin::ResourceController - before_action :load_payment_methods - before_action :load_shipping_methods +module Spree + module Admin + class StoresController < Spree::Admin::ResourceController + before_action :load_payment_methods + before_action :load_shipping_methods - def index - @stores = @stores.ransack(name_or_domains_or_code_cont: params[:q]).result if params[:q] - @stores = @stores.where(id: params[:ids].split(',')) if params[:ids] + def index + @stores = @stores.ransack(name_or_domains_or_code_cont: params[:q]).result if params[:q] + @stores = @stores.where(id: params[:ids].split(',')) if params[:ids] - respond_with(@stores) do |format| - format.html - format.json - end - end + respond_with(@stores) do |format| + format.html + format.json + end + end - private + private - def load_payment_methods - @payment_methods = Spree::PaymentMethod.all - end + def load_payment_methods + @payment_methods = Spree::PaymentMethod.all + end - def load_shipping_methods - @shipping_methods = Spree::ShippingMethod.all + def load_shipping_methods + @shipping_methods = Spree::ShippingMethod.all + end + end end end diff --git a/app/decorators/components/solidus_multi_domain/taxons_tree_component_decorator.rb b/app/decorators/components/solidus_multi_domain/taxons_tree_component_decorator.rb new file mode 100644 index 00000000..9963d54c --- /dev/null +++ b/app/decorators/components/solidus_multi_domain/taxons_tree_component_decorator.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module TaxonsTreeComponentDecorator + def self.prepended(base) + base.class_eval do + private + + def tree(root_taxon:, item_classes:, current_item_classes:, max_level:) + return if max_level < 1 || root_taxon.children.empty? + + filtered_taxons = root_taxon.children.joins(:taxonomy).where("spree_taxonomies.store_id = ?", + helpers.current_store.id).distinct + + content_tag :ul do + taxons = filtered_taxons.map do |taxon| + classes = item_classes + if current_item_classes && current_taxon&.self_and_ancestors&.include?(taxon) + classes = [classes, + current_item_classes].join(' ') + end + + content_tag :li, class: classes do + link_to(taxon.name, helpers.taxon_seo_url(taxon)) + + tree(root_taxon: taxon, item_classes: item_classes, current_item_classes: current_item_classes, + max_level: max_level - 1) + end + end + + safe_join([taxons], "\n") + end + end + end + end + + ::TaxonsTreeComponent.prepend self + end +end diff --git a/app/decorators/controllers/solidus_multi_domain/home_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/home_controller_decorator.rb new file mode 100644 index 00000000..16b77531 --- /dev/null +++ b/app/decorators/controllers/solidus_multi_domain/home_controller_decorator.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module HomeControllerDecorator + def index + @searcher = build_searcher(params) + @products = @searcher.retrieve_products + @taxonomies = get_taxonomies + # Split products into groups of 3 for the homepage blocks. + # You probably want to remove this logic and use your own! + homepage_groups = @products.in_groups_of(3, false) + @featured_products = homepage_groups[0] + @collection_products = homepage_groups[1] + @cta_collection_products = homepage_groups[2] + @new_arrivals = homepage_groups[3] + end + + ::HomeController.prepend(self) + end +end diff --git a/app/decorators/controllers/solidus_multi_domain/products_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/products_controller_decorator.rb new file mode 100644 index 00000000..32855c72 --- /dev/null +++ b/app/decorators/controllers/solidus_multi_domain/products_controller_decorator.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module ProductsControllerDecorator + def self.prepended(base) + base.prepend SolidusMultiDomain::ShowProductSupport + end + + def show + @variants = @product. + variants_including_master. + display_includes. + with_prices(current_pricing_options). + includes([:option_values, :images]) + @taxonomies = get_taxonomies + @product_properties = @product.product_properties.includes(:property) + @taxon = Spree::Taxon.find(params[:taxon_id]) if params[:taxon_id] + @similar_products = @product.similar_products.select { |product| product.stores.include?(current_store) } + end + + ::ProductsController.prepend(self) + end +end diff --git a/app/decorators/controllers/solidus_multi_domain/spree/admin/products_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/spree/admin/products_controller_decorator.rb index 6e1e1c6c..e18cd337 100644 --- a/app/decorators/controllers/solidus_multi_domain/spree/admin/products_controller_decorator.rb +++ b/app/decorators/controllers/solidus_multi_domain/spree/admin/products_controller_decorator.rb @@ -14,9 +14,9 @@ def self.prepended(base) def set_stores # Remove all store associations if store data is being passed and no stores are selected - if params[:update_store_ids] && !params[:product].key?(:store_ids) - @product.stores.clear - end + return unless params[:update_store_ids] && !params[:product].key?(:store_ids) + + @product.stores.clear end if SolidusMultiDomain::Engine.admin_available? diff --git a/app/decorators/controllers/solidus_multi_domain/spree/home_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/spree/home_controller_decorator.rb deleted file mode 100644 index 69e862a1..00000000 --- a/app/decorators/controllers/solidus_multi_domain/spree/home_controller_decorator.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module SolidusMultiDomain - module Spree - module HomeControllerDecorator - def index - @searcher = build_searcher(params) - @products = @searcher.retrieve_products - @taxonomies = get_taxonomies - end - - ::Spree::HomeController.prepend(self) if SolidusMultiDomain::Engine.frontend_available? - end - end -end diff --git a/app/decorators/controllers/solidus_multi_domain/spree/products_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/spree/products_controller_decorator.rb deleted file mode 100644 index fc55a13f..00000000 --- a/app/decorators/controllers/solidus_multi_domain/spree/products_controller_decorator.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module SolidusMultiDomain - module Spree - module ProductsControllerDecorator - def self.prepended(base) - base.prepend SolidusMultiDomain::ShowProductSupport - end - - ::Spree::ProductsController.prepend(self) if SolidusMultiDomain::Engine.frontend_available? - end - end -end diff --git a/app/decorators/controllers/solidus_multi_domain/spree/taxons_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/spree/taxons_controller_decorator.rb deleted file mode 100644 index 4bdd0ff3..00000000 --- a/app/decorators/controllers/solidus_multi_domain/spree/taxons_controller_decorator.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module SolidusMultiDomain - module Spree - module TaxonsControllerDecorator - def show - @taxon = ::Spree::Taxon.find_by_store_id_and_permalink!(current_store.id, params[:id]) - return unless @taxon - - @searcher = build_searcher(params.merge(taxon: @taxon.id)) - @products = @searcher.retrieve_products - @taxonomies = get_taxonomies - end - - ::Spree::TaxonsController.prepend(self) if SolidusMultiDomain::Engine.frontend_available? - end - end -end diff --git a/app/decorators/controllers/solidus_multi_domain/taxons_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/taxons_controller_decorator.rb new file mode 100644 index 00000000..615d9236 --- /dev/null +++ b/app/decorators/controllers/solidus_multi_domain/taxons_controller_decorator.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module TaxonsControllerDecorator + def show + @taxon = ::Spree::Taxon.find_by_store_id_and_permalink!(current_store.id, params[:id]) + return unless @taxon + @searcher = build_searcher(params.merge(taxon: @taxon.id)) + @products = @searcher.retrieve_products + @taxonomies = get_taxonomies + end + + ::TaxonsController.prepend(self) + end +end diff --git a/app/decorators/controllers/solidus_multi_domain/users_controller_decorator.rb b/app/decorators/controllers/solidus_multi_domain/users_controller_decorator.rb new file mode 100644 index 00000000..9870b826 --- /dev/null +++ b/app/decorators/controllers/solidus_multi_domain/users_controller_decorator.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module UsersControllerDecorator + def show + load_object + @orders = @user.orders.complete.by_store(current_store).order('completed_at desc') + end + + ::UsersController.prepend(self) + end +end diff --git a/app/decorators/helpers/solidus_multi_domain/spree/products_helper_decorator.rb b/app/decorators/helpers/solidus_multi_domain/spree/products_helper_decorator.rb index a5831101..259b3d2f 100644 --- a/app/decorators/helpers/solidus_multi_domain/spree/products_helper_decorator.rb +++ b/app/decorators/helpers/solidus_multi_domain/spree/products_helper_decorator.rb @@ -6,7 +6,12 @@ module ProductsHelperDecorator def self.prepended(base) base.module_eval do def get_taxonomies - @taxonomies ||= current_store.present? ? ::Spree::Taxonomy.where(["store_id = ?", current_store.id]) : ::Spree::Taxonomy + @taxonomies ||= if current_store.present? + ::Spree::Taxonomy.where(["store_id = ?", + current_store.id]) + else + ::Spree::Taxonomy + end @taxonomies = @taxonomies.includes(root: :children) @taxonomies end diff --git a/app/decorators/helpers/solidus_multi_domain/spree/taxons_helper_decorator.rb b/app/decorators/helpers/solidus_multi_domain/spree/taxons_helper_decorator.rb new file mode 100644 index 00000000..debfa831 --- /dev/null +++ b/app/decorators/helpers/solidus_multi_domain/spree/taxons_helper_decorator.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module SolidusMultiDomain + module Spree + module TaxonsHelperDecorator + def self.prepended(base) + base.module_eval do + def taxon_preview(taxon, max = 4) + price_scope = ::Spree::Price.where(current_pricing_options.search_arguments) + + products = taxon.active_products + .joins(:stores) + .where("spree_products_stores.store_id = ?", current_store.id) + .joins(:prices) + .merge(price_scope) + .select("DISTINCT spree_products.*, spree_products_taxons.position") + .limit(max) + + if products.size < max + products_arel = ::Spree::Product.arel_table + taxon.descendants.each do |descendent_taxon| + to_get = max - products.length + products += descendent_taxon.active_products + .joins(:stores) + .where("spree_products_stores.store_id = ?", current_store.id) + .joins(:prices) + .merge(price_scope) + .select("DISTINCT spree_products.*, spree_products_taxons.position") + .where(products_arel[:id].not_in(products.map(&:id))) + .limit(to_get) + break if products.size >= max + end + end + + products + end + end + end + + ::Spree::TaxonsHelper.prepend self + end + end +end diff --git a/app/decorators/lib/solidus_multi_domain/action_view/template_renderer_decorator.rb b/app/decorators/lib/solidus_multi_domain/action_view/template_renderer_decorator.rb index dda76fa1..74642b85 100644 --- a/app/decorators/lib/solidus_multi_domain/action_view/template_renderer_decorator.rb +++ b/app/decorators/lib/solidus_multi_domain/action_view/template_renderer_decorator.rb @@ -37,7 +37,7 @@ def controller_name end def api_request? - return true if controller_name.include?('::Api::') + true if controller_name.include?('::Api::') end ::ActionView::TemplateRenderer.prepend self diff --git a/app/decorators/models/solidus_multi_domain/spree/line_item_decorator.rb b/app/decorators/models/solidus_multi_domain/spree/line_item_decorator.rb index 2af28429..c38b89ff 100644 --- a/app/decorators/models/solidus_multi_domain/spree/line_item_decorator.rb +++ b/app/decorators/models/solidus_multi_domain/spree/line_item_decorator.rb @@ -12,9 +12,9 @@ def self.prepended(base) private def ensure_product_belongs_to_store - if order.store.present? && !product.stores.include?(order.store) - raise ProductDoesNotBelongToStoreError - end + return unless order.store.present? && !product.stores.include?(order.store) + + raise ProductDoesNotBelongToStoreError end ::Spree::LineItem.prepend self diff --git a/app/decorators/models/solidus_multi_domain/spree/store_decorator.rb b/app/decorators/models/solidus_multi_domain/spree/store_decorator.rb index 197c6e69..1da383ae 100644 --- a/app/decorators/models/solidus_multi_domain/spree/store_decorator.rb +++ b/app/decorators/models/solidus_multi_domain/spree/store_decorator.rb @@ -12,7 +12,8 @@ def self.prepended(base) has_many :store_shipping_methods has_many :shipping_methods, through: :store_shipping_methods - has_and_belongs_to_many :promotion_rules, class_name: 'Spree::Promotion::Rules::Store', join_table: 'spree_promotion_rules_stores', association_foreign_key: 'promotion_rule_id' + has_and_belongs_to_many :promotion_rules, class_name: 'Spree::Promotion::Rules::Store', + join_table: 'spree_promotion_rules_stores', association_foreign_key: 'promotion_rule_id' has_attached_file :logo, styles: { mini: '48x48>', small: '100x100>', medium: '250x250>' }, @@ -22,7 +23,7 @@ def self.prepended(base) convert_options: { all: '-strip -auto-orient' } validates_attachment_file_name :logo, matches: [/png\Z/i, /jpe?g\Z/i], - if: -> { respond_to?(:logo_file_name) } + if: -> { respond_to?(:logo_file_name) } end end diff --git a/app/models/spree/permission_sets/store_display.rb b/app/models/spree/permission_sets/store_display.rb index f6cb4cf4..309eaf9f 100644 --- a/app/models/spree/permission_sets/store_display.rb +++ b/app/models/spree/permission_sets/store_display.rb @@ -3,6 +3,16 @@ module Spree module PermissionSets class StoreDisplay < PermissionSets::Base + class << self + def privilege + :display + end + + def category + :store + end + end + def activate! can [:display, :admin], Spree::Store end diff --git a/app/models/spree/permission_sets/store_management.rb b/app/models/spree/permission_sets/store_management.rb index 57939649..890d1732 100644 --- a/app/models/spree/permission_sets/store_management.rb +++ b/app/models/spree/permission_sets/store_management.rb @@ -3,6 +3,16 @@ module Spree module PermissionSets class StoreManagement < PermissionSets::Base + class << self + def privilege + :manage + end + + def category + :store + end + end + def activate! can :manage, Spree::Store end diff --git a/app/models/spree/search/multi_domain.rb b/app/models/spree/search/multi_domain.rb index 511ff1c3..f2cd3de1 100644 --- a/app/models/spree/search/multi_domain.rb +++ b/app/models/spree/search/multi_domain.rb @@ -4,14 +4,15 @@ module Spree module Search class MultiDomain < Spree::Core::Search::Base def get_base_scope - base_scope = @cached_product_group ? @cached_product_group.products.available : Spree::Product.available - base_scope = base_scope.by_store(@properties[:current_store_id]) if @properties[:current_store_id].present? - base_scope = base_scope.in_taxon(@properties[:taxon]) if @properties[:taxon].present? + base_scope = Spree::Product.display_includes.available - base_scope = get_products_conditions_for(base_scope, @properties[:keywords]) if @properties[:keywords].present? + # This has been added to scope the search to the current store + base_scope = base_scope.by_store(@properties[:current_store_id]) if @properties[:current_store_id].present? + base_scope = base_scope.in_taxon(@properties[:taxon]) if @properties[:taxon].present? + base_scope = get_products_conditions_for(base_scope, @properties[:keywords]) base_scope = add_search_scopes(base_scope) - base_scope + add_eagerload_scopes(base_scope) end def prepare(params) diff --git a/app/overrides/decorate_admin_orders_index.rb b/app/overrides/decorate_admin_orders_index.rb new file mode 100644 index 00000000..77d43333 --- /dev/null +++ b/app/overrides/decorate_admin_orders_index.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module DecorateAdminOrdersIndex + Deface::Override.new( + virtual_path: "spree/admin/orders/index", + name: "multi_domain_admin_products_index_headers", + insert_before: "th.align-right", + partial: "spree/admin/orders/index_headers", + disabled: false + ) + + Deface::Override.new( + virtual_path: "spree/admin/orders/index", + name: "multi_domain_admin_products_index_rows", + insert_before: "td.align-right", + partial: "spree/admin/orders/index_rows", + disabled: false + ) +end diff --git a/app/views/spree/admin/orders/_index_headers.html.erb b/app/views/spree/admin/orders/_index_headers.html.erb new file mode 100644 index 00000000..5e078510 --- /dev/null +++ b/app/views/spree/admin/orders/_index_headers.html.erb @@ -0,0 +1 @@ +<%= I18n.t('spree.stores') %> diff --git a/app/views/spree/admin/orders/_index_rows.html.erb b/app/views/spree/admin/orders/_index_rows.html.erb new file mode 100644 index 00000000..6b277810 --- /dev/null +++ b/app/views/spree/admin/orders/_index_rows.html.erb @@ -0,0 +1 @@ +<%= order.store.name %> diff --git a/app/views/spree/admin/products/_index_rows.html.erb b/app/views/spree/admin/products/_index_rows.html.erb index c92ae243..5f316420 100644 --- a/app/views/spree/admin/products/_index_rows.html.erb +++ b/app/views/spree/admin/products/_index_rows.html.erb @@ -1 +1 @@ -<%= product.stores.map(&:code).join(", ") unless product.stores.empty? %> \ No newline at end of file +<%= product.stores.map(&:name).join(", ") unless product.stores.empty? %> diff --git a/app/views/spree/admin/products/_index_search_fields.html.erb b/app/views/spree/admin/products/_index_search_fields.html.erb index 2736dbf3..1ba1e706 100644 --- a/app/views/spree/admin/products/_index_search_fields.html.erb +++ b/app/views/spree/admin/products/_index_search_fields.html.erb @@ -1,4 +1,6 @@ -

-
- <%= f.select :stores_id_eq, Spree::Store.all.collect {|s| [s.name, s.id ] }, {:include_blank => true} %>

-

+
+
+
+ <%= f.select :stores_id_eq, Spree::Store.all.collect {|s| [s.name, s.id ] }, {:include_blank => true}, class:"custom-select fullwidth" %>

+
+
diff --git a/app/views/spree/admin/stores/new.html.erb b/app/views/spree/admin/stores/new.html.erb index c803eb41..a1bd64a2 100644 --- a/app/views/spree/admin/stores/new.html.erb +++ b/app/views/spree/admin/stores/new.html.erb @@ -6,7 +6,7 @@ <% content_for :page_actions do %>
  • - <%= button_link_to I18n.t('spree.back_to_store_list'), spree.admin_stores_path, :icon => 'icon-arrow-left' %> + <%= link_to I18n.t('spree.back_to_store_list'), spree.admin_stores_path, :icon => 'icon-arrow-left' %>
  • <% end %> diff --git a/bin/dummy-app b/bin/dummy-app new file mode 100755 index 00000000..9c08a661 --- /dev/null +++ b/bin/dummy-app @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +set -e + +extension_name="solidus_multi_domain" +# Stay away from the bundler env of the containing extension. +function unbundled { + ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- "$@" +} + +# "sqlite" is set by the ORB extension instead of "sqlite3", +# all other options are already in the format expected by `rails new`. +test "$DB" = "sqlite" && export DB="sqlite3" + +rm -rf ./dummy-app +rails_version=`bundle exec ruby -e'require "rails"; puts Rails.version'` +rails _${rails_version}_ new dummy-app \ + --database=${DB:-sqlite3} \ + --skip-git \ + --skip-keeps \ + --skip-rc \ + --skip-bootsnap \ + --skip-test + +if [ ! -d "dummy-app" ]; then + echo 'dummy-app rails application failed' + exit 1 +fi + +cd ./dummy-app +cat <> Gemfile +group :test, :development do + platforms :mri do + gem 'pry' + end +end +RUBY +unbundled bundle add solidus --github solidusio/solidus --branch "${BRANCH:-main}" --version '> 0.a' +unbundled bundle exec rake db:drop db:create +export FRONTEND_SPECS=skip +unbundled bundle exec rails generate solidus:install --auto-accept --payment-method=none --no-seed --no-sample"$@" +unbundled bundle add $extension_name --path .. +unbundled bundle exec rails generate $extension_name:install --auto-run-migrations --specs=all diff --git a/bin/rails b/bin/rails index 38e435ff..cd68cc76 100755 --- a/bin/rails +++ b/bin/rails @@ -7,7 +7,7 @@ app_root = 'sandbox' unless File.exist? "#{app_root}/bin/rails" warn 'Creating the sandbox app...' Dir.chdir "#{__dir__}/.." do - system "#{__dir__}/sandbox" or begin # rubocop:disable Style/AndOr + system "#{__dir__}/sandbox" or begin warn 'Automatic creation of the sandbox app failed' exit 1 end diff --git a/bin/rails-dummy-app b/bin/rails-dummy-app new file mode 100755 index 00000000..58a3513d --- /dev/null +++ b/bin/rails-dummy-app @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +root = "#{__dir__}/.." +app_root = "#{root}/dummy-app" + +unless File.exist? "#{app_root}/bin/rails" + warn 'Creating the dummy-app app...' + Dir.chdir root do + system "#{root}/bin/dummy-app" or begin + warn 'Automatic creation of the dummy-app app failed' + exit 1 + end + end +end + +Dir.chdir app_root +exec "#{app_root}/bin/rails", *ARGV diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 00000000..adeab88c --- /dev/null +++ b/bin/rspec @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +echo "Updating the dummy app..." +bin/rails-dummy-app generate solidus_multi_domain:install --force --auto-run-migrations --specs=all + +cd dummy-app/ +rspec "$@" +exit_status=$? +cd - +exit $exit_status diff --git a/bin/sandbox b/bin/sandbox index bfa58ae6..47cd7325 100755 --- a/bin/sandbox +++ b/bin/sandbox @@ -18,22 +18,28 @@ sqlite|'') ;; esac +if [ ! -z $SOLIDUS_BRANCH ] +then + BRANCH=$SOLIDUS_BRANCH +else + BRANCH="main" +fi + extension_name="solidus_multi_domain" # Stay away from the bundler env of the containing extension. function unbundled { - ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@ + ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- "$@" } rm -rf ./sandbox -unbundled bundle exec rails new sandbox --database="$RAILSDB" \ - --skip-bundle \ +rails new sandbox \ + --database="$RAILSDB" \ --skip-git \ --skip-keeps \ --skip-rc \ - --skip-spring \ - --skip-test \ - --skip-javascript + --skip-bootsnap \ + --skip-test if [ ! -d "sandbox" ]; then echo 'sandbox rails application failed' @@ -42,31 +48,22 @@ fi cd ./sandbox cat <> Gemfile - -gem '$extension_name', path: '..' -gem 'solidus_auth_devise', '>= 2.1.0' -gem 'rails-i18n' -gem 'solidus_i18n' - group :test, :development do platforms :mri do - gem 'pry-byebug' + gem 'pry' end end RUBY - -unbundled bundle install --gemfile Gemfile - +unbundled bundle add solidus --github solidusio/solidus --branch "${BRANCH:-main}" --version '> 0.a' unbundled bundle exec rake db:drop db:create - -unbundled bundle exec rails generate spree:install \ - --auto-accept \ - --user_class=Spree::User \ - --enforce_available_locales=true \ - $@ - -unbundled bundle exec rails generate solidus:auth:install +unbundled bundle exec rails generate solidus:install --payment-method=none --auto-accept "$@" +unbundled bundle add ${extension_name} --path '../' +unbundled bundle exec rails generate $extension_name:install --auto-run-migrations +bin/rails assets:precompile echo -echo "🚀 Sandbox app successfully created for $extension_name!" +echo "🚀 Sandbox app successfully created for ${extension_name}!" +echo "🚀 Using $RAILSDB and Solidus $BRANCH" +echo "🚀 Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter" +echo "🚀 Use 'export SOLIDUS_BRANCH=' to control the Solidus version" echo "🚀 This app is intended for test purposes." diff --git a/lib/generators/solidus_multi_domain/install/install_generator.rb b/lib/generators/solidus_multi_domain/install/install_generator.rb index 1bf26589..f65c839a 100644 --- a/lib/generators/solidus_multi_domain/install/install_generator.rb +++ b/lib/generators/solidus_multi_domain/install/install_generator.rb @@ -4,19 +4,55 @@ module SolidusMultiDomain module Generators class InstallGenerator < Rails::Generators::Base class_option :auto_run_migrations, type: :boolean, default: false + class_option :auto_copy_sample, type: :boolean, default: false + class_option :specs, type: :string, enum: %w[all], hide: true + + source_root File.expand_path('templates', __dir__) + + def handle_solidus_sample_data + return unless File.read('Gemfile').include?('solidus_sample') + + response = options[:auto_copy_sample] || ['', 'y', + 'Y'].include?(ask("Do you want to load sample data files? (y/n)")) + + if response + say "Copying sample data files..." + directory("sample_data", "db/samples") + say "Sample data files copied successfully." + else + say "Sample data files will not be copied." + end + end + + def generate_specs + return unless options[:specs] == 'all' + + spec_path = engine.root.join('spec') + + if spec_path.directory? + directory spec_path.to_s, 'spec' + else + say_status :error, "Spec directory not found: #{spec_path}", :red + end + end def add_migrations run 'bin/rails railties:install:migrations FROM=solidus_multi_domain' end def run_migrations - run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]')) + run_migrations = options[:auto_run_migrations] || ['', 'y', + 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]')) if run_migrations run 'bin/rails db:migrate' else puts 'Skipping bin/rails db:migrate, don\'t forget to run it!' # rubocop:disable Rails/Output end end + + def engine + SolidusMultiDomain::Engine + end end end end diff --git a/lib/generators/solidus_multi_domain/install/templates/sample_data/products.rb b/lib/generators/solidus_multi_domain/install/templates/sample_data/products.rb new file mode 100644 index 00000000..c784a30a --- /dev/null +++ b/lib/generators/solidus_multi_domain/install/templates/sample_data/products.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +Spree::Sample.load_sample("tax_categories") +Spree::Sample.load_sample("shipping_categories") + +tax_category = Spree::TaxCategory.find_by!(name: "Default") +shipping_category = Spree::ShippingCategory.find_by!(name: "Default") + +descriptions = [ + "Occaecati repellendus soluta perspiciatis ea ea voluptatum alias. Dolorem possimus sunt ipsam eos aliquam voluptates. Voluptate est nemo ullam cumque ea ut molestiae iste.", + "Nisi dolor explicabo est fugiat alias. Asperiores sunt rerum quisquam perspiciatis quis doloremque. Autem est harum eum dolorem voluptas nihil. Nulla omnis voluptas sint cumque ad ut dignissimos reiciendis. Mollitia culpa iure libero labore nulla autem non eum.", + "Perferendis sed voluptatem error ipsam voluptatem esse ipsa incidunt. Doloremque quos ratione quia voluptas consequatur mollitia optio. Optio sed iure aut aliquid voluptatum facilis mollitia cum. Dignissimos in saepe consequatur et consequatur dolorem blanditiis.", + "Necessitatibus optio quod ullam itaque quis corporis occaecati. Saepe harum voluptates consectetur rerum dolorum. Corrupti officiis reprehenderit quo excepturi cumque. Soluta eos perspiciatis aut et ea nulla amet dolores. Dolores distinctio nesciunt libero voluptas molestiae consequatur aut veritatis.", + "Soluta sed error debitis repellendus et. Voluptates unde enim qui velit. Libero earum tenetur nulla similique temporibus quod repellendus quibusdam.", + "Recusandae animi deserunt provident dignissimos ullam harum alias et. Itaque dicta maxime consectetur ut nemo non voluptatem. Voluptatem ipsum ut culpa eaque dolores.", +] + +default_attrs = { + description: descriptions.sample, + available_on: Time.current +} + +products = [ + { + name: "Solidus Water Bottle", + tax_category: tax_category, + shipping_category: shipping_category, + price: 19.99, + eur_price: 16, + weight: 0.5, + height: 20, + width: 10, + depth: 5, + }, + { + name: "Solidus tote", + tax_category: tax_category, + shipping_category: shipping_category, + price: 19.99, + eur_price: 16, + weight: 0.5, + height: 20, + width: 10, + depth: 5, + }, + { + name: "Solidus hoodie", + tax_category: tax_category, + shipping_category: shipping_category, + price: 29.99, + eur_price: 27, + weight: 1, + height: 20, + width: 10, + depth: 5, + }, + { + name: "Solidus mug set", + tax_category: tax_category, + shipping_category: shipping_category, + price: 19.99, + eur_price: 16, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus winter hat", + tax_category: tax_category, + shipping_category: shipping_category, + price: 29.99, + eur_price: 27, + weight: 1, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus circle sticker", + tax_category: tax_category, + shipping_category: shipping_category, + price: 29.99, + eur_price: 27, + weight: 0.8, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus notebook", + tax_category: tax_category, + shipping_category: shipping_category, + price: 26.99, + eur_price: 23, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus t-shirt", + tax_category: tax_category, + shipping_category: shipping_category, + price: 9.99, + eur_price: 7, + weight: 1, + height: 5, + width: 5, + depth: 5 + }, + { + name: "Solidus long sleeve tee", + tax_category: tax_category, + shipping_category: shipping_category, + price: 15.99, + eur_price: 14, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus dark tee", + tax_category: tax_category, + shipping_category: shipping_category, + price: 15.99, + eur_price: 14, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus canvas tote bag", + tax_category: tax_category, + shipping_category: shipping_category, + price: 15.99, + eur_price: 14, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + }, + { + name: "Solidus cap", + description: "Step into style with our signature cap – a perfect blend of comfort and trendsetting flair. Crafted with care and designed for the fashion-forward, this cap adds an instant touch of cool to any outfit. Whether you're hitting the streets or simply seeking shade, our cap is your go-to accessory. Elevate your look today!", + tax_category: tax_category, + shipping_category: shipping_category, + price: 24, + eur_price: 22, + weight: 0.5, + height: 20, + width: 10, + depth: 5 + } +] + +products.each do |product_attrs| + eur_price = product_attrs.delete(:eur_price) + Spree::Config[:currency] = "USD" + + product = Spree::Product.create!(default_attrs.merge(product_attrs)) + Spree::Config[:currency] = "EUR" + product.reload + product.price = eur_price + product.shipping_category = shipping_category + store = Spree::Store.first! # selects default store + product.stores << store + product.save! +end + +Spree::Config[:currency] = "USD" diff --git a/lib/generators/solidus_multi_domain/install/templates/sample_data/taxonomies.rb b/lib/generators/solidus_multi_domain/install/templates/sample_data/taxonomies.rb new file mode 100644 index 00000000..f6faec6c --- /dev/null +++ b/lib/generators/solidus_multi_domain/install/templates/sample_data/taxonomies.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +taxonomies = [ + { name: "Categories", store: Spree::Store.first! }, + { name: "Brands", store: Spree::Store.first! } +] + +taxonomies.each do |taxonomy_attrs| + Spree::Taxonomy.create!(taxonomy_attrs) +end diff --git a/lib/solidus_multi_domain/create_line_item_support.rb b/lib/solidus_multi_domain/create_line_item_support.rb index 9e29290b..5c60e57b 100644 --- a/lib/solidus_multi_domain/create_line_item_support.rb +++ b/lib/solidus_multi_domain/create_line_item_support.rb @@ -14,7 +14,8 @@ def self.prepended(base) private def product_does_not_belong_to_store - render json: { message: I18n.t('spree.errors.products_from_different_stores_may_not_be_added_to_this_order') }, status: :unprocessable_entity + render json: { message: I18n.t('spree.errors.products_from_different_stores_may_not_be_added_to_this_order') }, + status: :unprocessable_entity end end end diff --git a/lib/solidus_multi_domain/engine.rb b/lib/solidus_multi_domain/engine.rb index 57e375dd..6d67d6d0 100644 --- a/lib/solidus_multi_domain/engine.rb +++ b/lib/solidus_multi_domain/engine.rb @@ -20,7 +20,7 @@ def self.activate ApplicationController.include SolidusMultiDomain::MultiDomainHelpers end - config.to_prepare &method(:activate).to_proc + config.to_prepare(&method(:activate).to_proc) def self.admin_available? const_defined?('::Spree::Backend::Engine') @@ -29,9 +29,5 @@ def self.admin_available? def self.api_available? const_defined?('::Spree::Api::Engine') end - - def self.frontend_available? - const_defined?('::Spree::Frontend::Engine') - end end end diff --git a/lib/solidus_multi_domain/multi_domain_helpers.rb b/lib/solidus_multi_domain/multi_domain_helpers.rb index 7b274021..48df1f1e 100644 --- a/lib/solidus_multi_domain/multi_domain_helpers.rb +++ b/lib/solidus_multi_domain/multi_domain_helpers.rb @@ -4,10 +4,9 @@ module SolidusMultiDomain module MultiDomainHelpers extend ActiveSupport::Concern - include ::Spree::Core::ControllerHelpers::Common # layout :get_layout - include ::Spree::Core::ControllerHelpers::Store # current_store - included do + include ::Spree::Core::ControllerHelpers::Store # current_store + include ::Spree::Core::ControllerHelpers::Common # layout :get_layout helper 'spree/products' helper 'spree/taxons' @@ -16,7 +15,12 @@ module MultiDomainHelpers end def get_taxonomies - @taxonomies ||= current_store.present? ? ::Spree::Taxonomy.where(["store_id = ?", current_store.id]) : ::Spree::Taxonomy + @taxonomies ||= if current_store.present? + ::Spree::Taxonomy.where(["store_id = ?", + current_store.id]) + else + ::Spree::Taxonomy + end @taxonomies = @taxonomies.includes(root: :children) @taxonomies end diff --git a/lib/solidus_multi_domain/show_product_support.rb b/lib/solidus_multi_domain/show_product_support.rb index 952b167e..33c2ccca 100644 --- a/lib/solidus_multi_domain/show_product_support.rb +++ b/lib/solidus_multi_domain/show_product_support.rb @@ -12,9 +12,9 @@ def self.prepended(base) def can_show_product @product ||= ::Spree::Product.friendly.find(params[:id]) - if @product.stores.empty? || !@product.stores.include?(current_store) - raise ActiveRecord::RecordNotFound - end + return unless @product.stores.empty? || !@product.stores.include?(current_store) + + raise ActiveRecord::RecordNotFound end end end diff --git a/spec/controllers/spree/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb similarity index 94% rename from spec/controllers/spree/products_controller_spec.rb rename to spec/controllers/products_controller_spec.rb index 817769f1..71ee0b0a 100644 --- a/spec/controllers/spree/products_controller_spec.rb +++ b/spec/controllers/products_controller_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::ProductsController do +RSpec.describe ::ProductsController do let!(:product) { FactoryBot.create(:product) } describe 'on :show to a product without any stores' do diff --git a/spec/controllers/spree/admin/products_controller_spec.rb b/spec/controllers/spree/admin/products_controller_spec.rb index 8ca0014a..db6f1605 100644 --- a/spec/controllers/spree/admin/products_controller_spec.rb +++ b/spec/controllers/spree/admin/products_controller_spec.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Admin::ProductsController do +RSpec.describe Spree::Admin::ProductsController do + routes { Spree::Core::Engine.routes } stub_authorization! describe "on :index" do diff --git a/spec/controllers/spree/admin/stores_controller_spec.rb b/spec/controllers/spree/admin/stores_controller_spec.rb index 69a3ec9e..9f993dc0 100644 --- a/spec/controllers/spree/admin/stores_controller_spec.rb +++ b/spec/controllers/spree/admin/stores_controller_spec.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Admin::StoresController do +RSpec.describe Spree::Admin::StoresController do + routes { Spree::Core::Engine.routes } stub_authorization! describe '#index' do diff --git a/spec/controllers/spree/api/line_items_controller_spec.rb b/spec/controllers/spree/api/line_items_controller_spec.rb index 458f1820..8931742c 100644 --- a/spec/controllers/spree/api/line_items_controller_spec.rb +++ b/spec/controllers/spree/api/line_items_controller_spec.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Api::LineItemsController do +RSpec.describe Spree::Api::LineItemsController do + routes { Spree::Core::Engine.routes } before do stub_authentication! end diff --git a/spec/controllers/spree/api/shipments_controller_spec.rb b/spec/controllers/spree/api/shipments_controller_spec.rb index af588385..259386ea 100644 --- a/spec/controllers/spree/api/shipments_controller_spec.rb +++ b/spec/controllers/spree/api/shipments_controller_spec.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Api::ShipmentsController do +RSpec.describe Spree::Api::ShipmentsController do + routes { Spree::Core::Engine.routes } describe '#mine' do let!(:user) { FactoryBot.create(:user) } let!(:store1) { FactoryBot.create(:store) } diff --git a/spec/helpers/products_helper_decorator_spec.rb b/spec/helpers/products_helper_decorator_spec.rb index 1231600b..fe200c2c 100644 --- a/spec/helpers/products_helper_decorator_spec.rb +++ b/spec/helpers/products_helper_decorator_spec.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' module Spree - describe ProductsHelper do + RSpec.describe ProductsHelper do before do @store = FactoryBot.create(:store) @taxonomy = FactoryBot.create(:taxonomy, store: @store) diff --git a/spec/lib/spree_multi_domain/testing_support/factory_overrides_spec.rb b/spec/lib/spree_multi_domain/testing_support/factory_overrides_spec.rb index 30c4580f..21476ace 100644 --- a/spec/lib/spree_multi_domain/testing_support/factory_overrides_spec.rb +++ b/spec/lib/spree_multi_domain/testing_support/factory_overrides_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe "spree core factories should not raise ProductDoesNotBelongToStoreError" do +RSpec.describe "spree core factories should not raise ProductDoesNotBelongToStoreError" do it "is able to build a line_item" do expect { build(:line_item) }.not_to raise_error end diff --git a/spec/models/spree/line_item_spec.rb b/spec/models/spree/line_item_spec.rb index ada95bc3..a37deb1b 100644 --- a/spec/models/spree/line_item_spec.rb +++ b/spec/models/spree/line_item_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::LineItem do +RSpec.describe Spree::LineItem do describe "before create" do subject { line_item.save! } @@ -18,10 +18,9 @@ if version && version >= Gem::Version.new("1.3.0.alpha") skip "As of 1.3.0 Orders must have a store" end + order.update(store_id: nil) end - before { order.update(store_id: nil) } - let(:product) { create(:product, stores: [order_store]) } it 'does not raise an error' do diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index e5cdc4cb..abdde6b1 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -1,6 +1,3 @@ # frozen_string_literal: true -require 'spec_helper' - -describe Spree::Order do -end +require 'solidus_multi_domain_spec_helper' diff --git a/spec/models/spree/permission_sets/store_display_spec.rb b/spec/models/spree/permission_sets/store_display_spec.rb index d8970905..08eaa6fa 100644 --- a/spec/models/spree/permission_sets/store_display_spec.rb +++ b/spec/models/spree/permission_sets/store_display_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::PermissionSets::StoreDisplay do +RSpec.describe Spree::PermissionSets::StoreDisplay do subject { ability } let(:ability) { Spree::Ability.new nil } diff --git a/spec/models/spree/permission_sets/store_management_spec.rb b/spec/models/spree/permission_sets/store_management_spec.rb index 1e42bc1c..2cbfb9e6 100644 --- a/spec/models/spree/permission_sets/store_management_spec.rb +++ b/spec/models/spree/permission_sets/store_management_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::PermissionSets::StoreManagement do +RSpec.describe Spree::PermissionSets::StoreManagement do subject { ability } let(:ability) { Spree::Ability.new nil } diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index a9874658..1b7891d6 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Product do +RSpec.describe Spree::Product do before do @store = FactoryBot.create(:store) @product = FactoryBot.create(:product, stores: [@store]) diff --git a/spec/models/spree/shipping_method_decorator_spec.rb b/spec/models/spree/shipping_method_decorator_spec.rb index f3c520db..297bbe88 100644 --- a/spec/models/spree/shipping_method_decorator_spec.rb +++ b/spec/models/spree/shipping_method_decorator_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::ShippingMethod do +RSpec.describe Spree::ShippingMethod do let(:shipping_method) { create :shipping_method } let(:order) { create :order, store: store } let(:store) { create :store } diff --git a/spec/models/spree/store_spec.rb b/spec/models/spree/store_spec.rb index a7e87eac..0ca4c388 100644 --- a/spec/models/spree/store_spec.rb +++ b/spec/models/spree/store_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Store do +RSpec.describe Spree::Store do let!(:default_store) { FactoryBot.create(:store, default: true, url: "default.com") } let!(:store_2) { FactoryBot.create(:store, code: 'STORE2', url: 'freethewhales.com') } let!(:store_3) { FactoryBot.create(:store, code: 'STORE3', url: "website1.com\nwww.subdomain.com") } diff --git a/spec/models/spree/taxon_decorator_spec.rb b/spec/models/spree/taxon_decorator_spec.rb index aca017d3..e5076cf0 100644 --- a/spec/models/spree/taxon_decorator_spec.rb +++ b/spec/models/spree/taxon_decorator_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe Spree::Taxon do +RSpec.describe Spree::Taxon do describe ".find_by_store_id_and_permalink!" do context "taxon exist in given store" do let!(:store) { FactoryBot.create :store } diff --git a/spec/requests/global_controller_helpers_spec.rb b/spec/requests/global_controller_helpers_spec.rb index 58166ded..c9dd9252 100644 --- a/spec/requests/global_controller_helpers_spec.rb +++ b/spec/requests/global_controller_helpers_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe "Global controller helpers" do +RSpec.describe "Global controller helpers" do let!(:store) { FactoryBot.create :store } before do diff --git a/spec/requests/spree/api/products_controller_spec.rb b/spec/requests/spree/api/products_controller_spec.rb index c548456b..0184ecf5 100644 --- a/spec/requests/spree/api/products_controller_spec.rb +++ b/spec/requests/spree/api/products_controller_spec.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' + +RSpec.describe Spree::Api::ProductsController, type: :request do + subject { + get "/api/products/#{product.to_param}", headers: headers + } -describe Spree::Api::ProductsController, type: :request do let!(:product) { FactoryBot.create(:product) } let!(:user) { create(:user, :with_api_key) } let!(:store) { FactoryBot.create(:store) } @@ -13,10 +17,6 @@ let!(:headers) { { 'X-Spree-Token' => user.spree_api_key } } end - subject { - get "/api/products/#{product.to_param}", headers: headers - } - describe :show do context 'when the product is not added to the store' do it 'returns 404' do diff --git a/spec/requests/template_renderer_spec.rb b/spec/requests/template_renderer_spec.rb index 781ec2de..e6a94f2d 100644 --- a/spec/requests/template_renderer_spec.rb +++ b/spec/requests/template_renderer_spec.rb @@ -1,14 +1,16 @@ # frozen_string_literal: true -require 'spec_helper' +require 'solidus_multi_domain_spec_helper' -describe "Template renderer with dynamic layouts" do +RSpec.describe "Template renderer with dynamic layouts" do before do @old_view_paths = ApplicationController.view_paths ApplicationController.view_paths = [ActionView::FixtureResolver.new( "spree/layouts/spree_application.html.erb" => "Default layout <%= yield %>", "spree/layouts/my_store/spree_application.html.erb" => "Store layout <%= yield %>", + "layouts/my_store/storefront.html.erb" => "Storefront layout <%= yield %>", + "layouts/storefront.html.erb" => "Default storefront layout <%= yield %>", "application/index.html.erb" => "hello" )] end @@ -21,12 +23,12 @@ it "renders the layout corresponding to the current store" do get "http://#{store.url}" - expect(response.body).to eql("Store layout hello") + expect(response.body).to eql("Storefront layout hello") end it "falls back to the default layout if none are found for the current store" do get "http://www.example.com" - expect(response.body).to eql("Default layout hello") + expect(response.body).to eql("Default storefront layout hello") end context "for a controller inheriting from ApplicationController" do @@ -40,7 +42,7 @@ )] Rails.application.routes.draw do - get 'normal', to: 'normal#index' # rubocop:disable Rails/HttpPositionalArguments + get 'normal', to: 'normal#index' end end @@ -75,9 +77,7 @@ def index )] Rails.application.routes.draw do - # rubocop:disable Rails/HttpPositionalArguments get 'explicit_layout', to: 'explicit_layout#index' - # rubocop:enable Rails/HttpPositionalArguments end end diff --git a/spec/solidus_multi_domain_spec_helper.rb b/spec/solidus_multi_domain_spec_helper.rb new file mode 100644 index 00000000..762ff3a7 --- /dev/null +++ b/spec/solidus_multi_domain_spec_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'solidus_starter_frontend_spec_helper' +require 'support/solidus_multi_domain/testing_support/factories' +require 'solidus_core' +require 'solidus_api' +require 'solidus_backend' +require 'spree/testing_support/authorization_helpers' +require 'spree/testing_support/url_helpers' +require 'support/api' +require 'support/cancan' + +RSpec.configure do |config| + config.include Spree::TestingSupport::UrlHelpers +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 648ce64b..00000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -# Configure Rails Environment -ENV['RAILS_ENV'] = 'test' - -# Run Coverage report -require 'solidus_dev_support/rspec/coverage' - -require File.expand_path('dummy/config/environment.rb', __dir__) - -# Requires factories and other useful helpers defined in spree_core. -require 'solidus_dev_support/rspec/feature_helper' - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f } - -# Requires factories defined in lib/solidus_multi_domain/testing_support/factories.rb -SolidusDevSupport::TestingSupport::Factories.load_for(SolidusMultiDomain::Engine) - -RSpec.configure do |config| - config.infer_spec_type_from_file_location! - config.use_transactional_fixtures = false - config.include Devise::Test::ControllerHelpers, type: :controller -end diff --git a/spec/support/api.rb b/spec/support/api.rb index 04fe364d..8b8bbe1d 100644 --- a/spec/support/api.rb +++ b/spec/support/api.rb @@ -4,6 +4,5 @@ require 'spree/api/testing_support/helpers' RSpec.configure do |config| - config.include Spree::TestingSupport::ControllerRequests, type: :controller config.include Spree::Api::TestingSupport::Helpers, type: :controller end diff --git a/lib/solidus_multi_domain/testing_support/factories.rb b/spec/support/solidus_multi_domain/testing_support/factories.rb similarity index 99% rename from lib/solidus_multi_domain/testing_support/factories.rb rename to spec/support/solidus_multi_domain/testing_support/factories.rb index 805fc802..fdecc6ec 100644 --- a/lib/solidus_multi_domain/testing_support/factories.rb +++ b/spec/support/solidus_multi_domain/testing_support/factories.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + FactoryBot.use_parent_strategy = false FactoryBot.modify do