diff --git a/Gemfile b/Gemfile index 8fd65ce01..8bd4dbb4f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,8 @@ ruby File.open('.ruby-version').readline.chomp #=== CORE ===================================================================== gem 'acts-as-taggable-on', git: 'https://github.com/Fodoj/acts-as-taggable-on', ref: 'rails-5.2' gem 'carrierwave', '~> 1.2' +gem "mini_magick" +gem 'rmagick' gem 'devise', '~> 4.7.1' gem 'friendly_id', '~> 5.1' gem 'kaminari' @@ -23,6 +25,7 @@ gem 'sidekiq-scheduler', '~> 2.1.4' gem 'simple_form' gem 'courses', path: 'components/courses' +gem 'shop', path: 'components/shop' gem 'ez-settings' #=== CONFIG =================================================================== @@ -38,8 +41,8 @@ gem 'autoprefixer-rails', '~> 7.1.6' gem 'coffee-rails', '~> 4.2.1' gem 'jquery-rails', '~> 4.2.2' gem 'premailer-rails' # email inline styling -gem 'rails-assets-semantic-ui-calendar', source: 'https://rails-assets.org' -gem 'rails-assets-svgxuse', source: 'https://rails-assets.org' +gem 'rails-assets-semantic-ui-calendar', source: 'http://insecure.rails-assets.org' +gem 'rails-assets-svgxuse', source: 'http://insecure.rails-assets.org' gem 'sass-rails', '~> 5.0' gem 'semantic-ui-sass', '~> 2.2' gem 'slim-rails' diff --git a/Gemfile.lock b/Gemfile.lock index c0d5e45ca..703e125f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,13 +12,24 @@ PATH courses (0.1.0) friendly_id kaminari - rails + rails (~> 5.2.2, >= 5.2.2.1) + simple_form + slim-rails + +PATH + remote: components/shop + specs: + shop (0.1.0) + carrierwave (~> 1.2) + friendly_id + kaminari + rails (~> 5.2.2, >= 5.2.2.1) simple_form slim-rails GEM remote: https://rubygems.org/ - remote: https://rails-assets.org/ + remote: http://insecure.rails-assets.org/ specs: Ascii85 (1.0.3) actioncable (5.2.5) @@ -302,6 +313,7 @@ GEM mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2019.1009) + mini_magick (4.11.0) mini_mime (1.1.0) mini_portile2 (2.5.1) minitest (5.14.4) @@ -449,6 +461,7 @@ GEM mime-types (>= 1.16, < 4.0) netrc (~> 0.8) rexml (3.2.4) + rmagick (4.2.2) rollbar (2.19.4) multi_json rqrcode (1.1.2) @@ -651,6 +664,7 @@ DEPENDENCIES letter_opener listen meta_request + mini_magick newrelic_rpm (~> 5.4) oj (~> 3.7.11) omniauth-facebook (~> 5.0) @@ -673,6 +687,7 @@ DEPENDENCIES recaptcha redcarpet (~> 3.4.0) redis (~> 3.2) + rmagick rollbar (~> 2.19.3) rspec rspec-activemodel-mocks @@ -684,6 +699,7 @@ DEPENDENCIES rubocop-rspec sass-rails (~> 5.0) semantic-ui-sass (~> 2.2) + shop! shoulda-matchers sidekiq sidekiq-scheduler (~> 2.1.4) diff --git a/app/assets/stylesheets/app/application.scss b/app/assets/stylesheets/app/application.scss index 1c90b1ecf..784c887b6 100644 --- a/app/assets/stylesheets/app/application.scss +++ b/app/assets/stylesheets/app/application.scss @@ -54,6 +54,8 @@ @import "pages/courses/form"; @import "pages/courses/seasons"; +@import "pages/shop/items"; + @import "pages/donate/form"; @import "pages/agenda/agenda"; diff --git a/app/assets/stylesheets/app/pages/shop/_items.scss b/app/assets/stylesheets/app/pages/shop/_items.scss new file mode 100644 index 000000000..87804ddab --- /dev/null +++ b/app/assets/stylesheets/app/pages/shop/_items.scss @@ -0,0 +1,89 @@ +.main{ + max-width: 1200px; + margin: 0 auto; +} + +h1 { + font-size: 24px; + font-weight: 400; + text-align: center; +} + +img { + height: auto; + max-width: 100%; + vertical-align: middle; +} + +.btn { + color: #ffffff; + padding: 0.8rem; + font-size: 14px; + text-transform: uppercase; + border-radius: 4px; + font-weight: 400; + display: block; + width: 100%; + cursor: pointer; + border: 1px solid rgba(255, 255, 255, 0.2); + background: transparent; +} + +.btn:hover { + background-color: rgba(255, 255, 255, 0.12); +} + +.cards { + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; +} + +.cards_item { + display: flex; + padding: 1rem; +} + +@media (min-width: 40rem) { + .cards_item { + width: 50%; + } +} + +@media (min-width: 56rem) { + .cards_item { + width: 33.3333%; + } +} + +.card { + background-color: white; + border-radius: 0.25rem; + box-shadow: 0 20px 40px -14px rgba(0, 0, 0, 0.25); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.card_content { + padding: 1rem; + background: linear-gradient(to bottom left, #ce5739 40%, #FFC39E 100%); +} + +.card_title { + color: #ffffff; + font-size: 1.1rem; + font-weight: 700; + letter-spacing: 1px; + text-transform: capitalize; + margin: 0px; +} + +.card_text { + color: #ffffff; + font-size: 0.875rem; + line-height: 1.5; + margin-bottom: 1.25rem; + font-weight: 400; +} diff --git a/app/helpers/admin/navigation_helper.rb b/app/helpers/admin/navigation_helper.rb index 4993de88a..e9a8e5803 100644 --- a/app/helpers/admin/navigation_helper.rb +++ b/app/helpers/admin/navigation_helper.rb @@ -52,6 +52,10 @@ def admin_pages_link link_to t('pages.plural'), admin_pages_path, class: class_for(:pages) end + def admin_shop_link + link_to t('shop.singular'), admin_shop_items_path, class: class_for(:shop) + end + private def class_for(item) diff --git a/app/uploaders/default_image_uploader.rb b/app/uploaders/default_image_uploader.rb index c9bc16230..e5f3a5661 100644 --- a/app/uploaders/default_image_uploader.rb +++ b/app/uploaders/default_image_uploader.rb @@ -3,7 +3,19 @@ class DefaultImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick - # include CarrierWave::MiniMagick + include CarrierWave::MiniMagick + + version :small do + process resize_to_fill: [60, 60] + end + + version :middle do + process resize_to_fill: [295, 295] + end + + version :large do + process resize_to_fill: [1200, 1200] + end # Choose what kind of storage to use for this uploader: storage :file diff --git a/app/uploaders/item_image_uploader.rb b/app/uploaders/item_image_uploader.rb new file mode 100644 index 000000000..a7d6f1322 --- /dev/null +++ b/app/uploaders/item_image_uploader.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class ItemImageUploader < DefaultImageUploader +end diff --git a/app/views/layouts/admin/_navigation.slim b/app/views/layouts/admin/_navigation.slim index 075c84094..23557d89d 100644 --- a/app/views/layouts/admin/_navigation.slim +++ b/app/views/layouts/admin/_navigation.slim @@ -9,7 +9,7 @@ = admin_email_templates_link = admin_friends_link = admin_pages_link - += admin_shop_link // TOOD @VS: Move all menu items to registry. Or not ? - Ez::Registry.data(:admin_primary_navigation).each do |menu_item| diff --git a/app/views/layouts/app/_header.slim b/app/views/layouts/app/_header.slim index 4bf9d5d26..fa6c0b955 100644 --- a/app/views/layouts/app/_header.slim +++ b/app/views/layouts/app/_header.slim @@ -18,6 +18,8 @@ header.pk-header class="#{header_classlist.compact.join(' ')}" .pk-header__dropdown-list-wr nav ul.pk-list.pk-header__dropdown-list.js-dropdown-list + li.pk-list__unit.pk-header__li-list-wr + = link_to "shop", '/shop/items' li.pk-list__unit.pk-header__li-list-wr a = "info" ul.pk-header__li-list diff --git a/components/courses/Gemfile.lock b/components/courses/Gemfile.lock index 258b447e1..72aa33c7d 100644 --- a/components/courses/Gemfile.lock +++ b/components/courses/Gemfile.lock @@ -4,7 +4,7 @@ PATH courses (0.1.0) friendly_id kaminari - rails + rails (~> 5.2.2, >= 5.2.2.1) simple_form slim-rails @@ -79,7 +79,7 @@ GEM i18n (>= 0.7) ffi (1.10.0) formatador (0.2.5) - friendly_id (5.2.5) + friendly_id (5.4.2) activerecord (>= 4.0.0) globalid (0.4.2) activesupport (>= 4.2.0) @@ -100,18 +100,18 @@ GEM i18n (1.6.0) concurrent-ruby (~> 1.0) json (2.2.0) - kaminari (1.1.1) + kaminari (1.2.1) activesupport (>= 4.1.0) - kaminari-actionview (= 1.1.1) - kaminari-activerecord (= 1.1.1) - kaminari-core (= 1.1.1) - kaminari-actionview (1.1.1) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) actionview - kaminari-core (= 1.1.1) - kaminari-activerecord (1.1.1) + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) activerecord - kaminari-core (= 1.1.1) - kaminari-core (1.1.1) + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) launchy (2.4.3) addressable (~> 2.3) listen (3.1.5) @@ -127,12 +127,14 @@ GEM marcel (0.3.3) mimemagic (~> 0.3.2) method_source (0.9.2) - mimemagic (0.3.3) + mimemagic (0.3.10) + nokogiri (~> 1) + rake mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) nenv (0.3.0) - nio4r (2.3.1) + nio4r (2.5.7) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) notiffany (0.1.1) @@ -199,38 +201,38 @@ GEM rspec-support (3.8.0) ruby_dep (1.5.0) shellany (0.0.1) - simple_form (4.1.0) - actionpack (>= 5.0) - activemodel (>= 5.0) + simple_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - slim (4.0.1) + slim (4.1.0) temple (>= 0.7.6, < 0.9) tilt (>= 2.0.6, < 2.1) slim-rails (3.2.0) actionpack (>= 3.1) railties (>= 3.1) slim (>= 3.0, < 5.0) - sprockets (3.7.2) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) - temple (0.8.1) + temple (0.8.2) thor (0.20.3) thread_safe (0.3.6) - tilt (2.0.9) + tilt (2.0.10) tzinfo (1.2.5) thread_safe (~> 0.1) - websocket-driver (0.7.0) + websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) + websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) @@ -250,4 +252,4 @@ DEPENDENCIES sqlite3 (~> 1.3.6) BUNDLED WITH - 1.16.1 + 1.17.2 diff --git a/components/courses/courses.gemspec b/components/courses/courses.gemspec index 09b48dce8..cd79592c7 100644 --- a/components/courses/courses.gemspec +++ b/components/courses/courses.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency 'friendly_id' s.add_dependency 'kaminari' - s.add_dependency 'rails' + s.add_dependency 'rails', '~> 5.2.2', '>= 5.2.2.1' s.add_dependency 'simple_form' s.add_dependency 'slim-rails' diff --git a/components/shop/.gitignore b/components/shop/.gitignore new file mode 100644 index 000000000..d9548baa4 --- /dev/null +++ b/components/shop/.gitignore @@ -0,0 +1,10 @@ +.bundle/ +log/*.log +pkg/ +spec/dummy/db/*.sqlite3 +spec/dummy/db/*.sqlite3-journal +spec/dummy/log/*.log +spec/dummy/node_modules/ +spec/dummy/yarn-error.log +spec/dummy/storage/ +spec/dummy/tmp/ diff --git a/components/shop/Gemfile b/components/shop/Gemfile new file mode 100644 index 000000000..173ba3af4 --- /dev/null +++ b/components/shop/Gemfile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +# Declare your gem's dependencies in shop.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use a debugger +# gem 'byebug', group: [:development, :test] diff --git a/components/shop/Gemfile.lock b/components/shop/Gemfile.lock new file mode 100644 index 000000000..08a0af1a7 --- /dev/null +++ b/components/shop/Gemfile.lock @@ -0,0 +1,259 @@ +PATH + remote: . + specs: + shop (0.1.0) + carrierwave (~> 1.2) + friendly_id + kaminari + rails (~> 5.2.2, >= 5.2.2.1) + simple_form + slim-rails + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.6) + actionpack (= 5.2.6) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.6) + actionview (= 5.2.6) + activesupport (= 5.2.6) + rack (~> 2.0, >= 2.0.8) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.6) + activesupport (= 5.2.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.6) + activesupport (= 5.2.6) + globalid (>= 0.3.6) + activemodel (5.2.6) + activesupport (= 5.2.6) + activerecord (5.2.6) + activemodel (= 5.2.6) + activesupport (= 5.2.6) + arel (>= 9.0) + activestorage (5.2.6) + actionpack (= 5.2.6) + activerecord (= 5.2.6) + marcel (~> 1.0.0) + activesupport (5.2.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + arel (9.0.0) + builder (3.2.4) + capybara (3.35.3) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + carrierwave (1.3.2) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) + ssrf_filter (~> 1.0) + coderay (1.1.3) + concurrent-ruby (1.1.8) + crass (1.0.6) + diff-lcs (1.4.4) + docile (1.4.0) + erubi (1.10.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (2.18.0) + i18n (>= 1.6, < 2) + ffi (1.15.0) + formatador (0.2.5) + friendly_id (5.4.2) + activerecord (>= 4.0.0) + globalid (0.4.2) + activesupport (>= 4.2.0) + guard (2.17.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + i18n (1.8.10) + concurrent-ruby (~> 1.0) + kaminari (1.2.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) + actionview + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) + activerecord + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) + launchy (2.5.0) + addressable (~> 2.7) + listen (3.5.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + loofah (2.9.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.2.8) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (1.0.1) + method_source (1.0.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2021.0225) + mini_mime (1.1.0) + minitest (5.14.4) + nenv (0.3.0) + nio4r (2.5.7) + nokogiri (1.11.3-x86_64-darwin) + racc (~> 1.4) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + pry (0.14.1) + coderay (~> 1.1) + method_source (~> 1.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (4.0.6) + racc (1.5.2) + rack (2.2.3) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.6) + actioncable (= 5.2.6) + actionmailer (= 5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + activemodel (= 5.2.6) + activerecord (= 5.2.6) + activestorage (= 5.2.6) + activesupport (= 5.2.6) + bundler (>= 1.3.0) + railties (= 5.2.6) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.6) + actionpack (= 5.2.6) + activesupport (= 5.2.6) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rake (13.0.3) + rb-fsevent (0.11.0) + rb-inotify (0.10.1) + ffi (~> 1.0) + regexp_parser (2.1.1) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-rails (5.0.1) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.2) + shellany (0.0.1) + simple_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) + simplecov (0.21.2) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.3) + slim (4.1.0) + temple (>= 0.7.6, < 0.9) + tilt (>= 2.0.6, < 2.1) + slim-rails (3.2.0) + actionpack (>= 3.1) + railties (>= 3.1) + slim (>= 3.0, < 5.0) + sprockets (4.0.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.2) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.4.2) + ssrf_filter (1.0.7) + temple (0.8.2) + thor (1.1.0) + thread_safe (0.3.6) + tilt (2.0.10) + tzinfo (1.2.9) + thread_safe (~> 0.1) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + +PLATFORMS + x86_64-darwin-20 + +DEPENDENCIES + capybara + factory_bot_rails + faker + guard-rspec + launchy + pry-rails + rspec-rails + shop! + simplecov + sqlite3 + +BUNDLED WITH + 2.2.16 diff --git a/components/shop/Guardfile b/components/shop/Guardfile new file mode 100644 index 000000000..f682475b1 --- /dev/null +++ b/components/shop/Guardfile @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +# rubocop:disable Metrics/BlockLength + +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# NOTE: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: 'bundle exec rspec' do + require 'guard/rspec/dsl' + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w[erb haml slim]) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' + end +end + +# rubocop:enable Metrics/BlockLength diff --git a/components/shop/MIT-LICENSE b/components/shop/MIT-LICENSE new file mode 100644 index 000000000..effd19ad4 --- /dev/null +++ b/components/shop/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2021 Vasia Ivanyshak + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/components/shop/README.md b/components/shop/README.md new file mode 100644 index 000000000..7a19083d1 --- /dev/null +++ b/components/shop/README.md @@ -0,0 +1,28 @@ +# Shop +Short description and motivation. + +## Usage +How to use my plugin. + +## Installation +Add this line to your application's Gemfile: + +```ruby +gem 'shop' +``` + +And then execute: +```bash +$ bundle +``` + +Or install it yourself as: +```bash +$ gem install shop +``` + +## Contributing +Contribution directions go here. + +## License +The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). diff --git a/components/shop/Rakefile b/components/shop/Rakefile new file mode 100644 index 000000000..b81a9b0cd --- /dev/null +++ b/components/shop/Rakefile @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Shop' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.md') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__) +load 'rails/tasks/engine.rake' + +load 'rails/tasks/statistics.rake' + +require 'bundler/gem_tasks' + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +task default: :test diff --git a/components/shop/app/assets/config/shop_manifest.js b/components/shop/app/assets/config/shop_manifest.js new file mode 100644 index 000000000..1aaab3174 --- /dev/null +++ b/components/shop/app/assets/config/shop_manifest.js @@ -0,0 +1,2 @@ +//= link_directory ../javascripts/shop .js +//= link_directory ../stylesheets/shop .css diff --git a/components/shop/app/assets/images/shop/.keep b/components/shop/app/assets/images/shop/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/app/assets/javascripts/shop/application.js b/components/shop/app/assets/javascripts/shop/application.js new file mode 100644 index 000000000..67ce4675c --- /dev/null +++ b/components/shop/app/assets/javascripts/shop/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require rails-ujs +//= require activestorage +//= require_tree . diff --git a/components/shop/app/assets/stylesheets/scaffold.css b/components/shop/app/assets/stylesheets/scaffold.css new file mode 100644 index 000000000..cd4f3de38 --- /dev/null +++ b/components/shop/app/assets/stylesheets/scaffold.css @@ -0,0 +1,80 @@ +body { + background-color: #fff; + color: #333; + margin: 33px; +} + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; +} + +a:visited { + color: #666; +} + +a:hover { + color: #fff; + background-color: #000; +} + +th { + padding-bottom: 5px; +} + +td { + padding: 0 5px 7px; +} + +div.field, +div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px 7px 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px -7px 0; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} + +label { + display: block; +} diff --git a/components/shop/app/assets/stylesheets/shop/application.css b/components/shop/app/assets/stylesheets/shop/application.css new file mode 100644 index 000000000..0ebd7fe82 --- /dev/null +++ b/components/shop/app/assets/stylesheets/shop/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/components/shop/app/controllers/admin/shop/base_controller.rb b/components/shop/app/controllers/admin/shop/base_controller.rb new file mode 100644 index 000000000..c4897ae23 --- /dev/null +++ b/components/shop/app/controllers/admin/shop/base_controller.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Admin + module Shop + class BaseController < ::Admin::BaseController + end + end +end diff --git a/components/shop/app/controllers/admin/shop/items_controller.rb b/components/shop/app/controllers/admin/shop/items_controller.rb new file mode 100644 index 000000000..8d5c1771d --- /dev/null +++ b/components/shop/app/controllers/admin/shop/items_controller.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Admin + module Shop + class ItemsController < ::Admin::Shop::BaseController + helper_method :item, :items + + def new + @item = ::Shop::Item.new + render_form + end + + def edit + item + render_form + end + + def create + item = ::Shop::Item.new(items_params) + + react_to item.save + end + + def update + react_to item.update(items_params) + end + + private + + def default_redirect + redirect_to admin_shop_items_path + end + + def item + @item ||= ::Shop::Item.find(params[:id]) + end + + def items + @items ||= ::Shop::Item.all + end + + def items_params + params.require(:item).permit(:name, :description, :price, :available_qty, :published, + item_images_attributes: [:image]) + end + end + end +end diff --git a/components/shop/app/controllers/shop/base_controller.rb b/components/shop/app/controllers/shop/base_controller.rb new file mode 100644 index 000000000..bc4a29bb8 --- /dev/null +++ b/components/shop/app/controllers/shop/base_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Shop + class BaseController < ApplicationController + before_action :authenticate_user! + + private + + def render_form + render :form + end + + def react_to(action) + if action + flash_success && default_redirect + else + flash_error && render_form + end + end + end +end diff --git a/components/shop/app/controllers/shop/items_controller.rb b/components/shop/app/controllers/shop/items_controller.rb new file mode 100644 index 000000000..a3dfaa367 --- /dev/null +++ b/components/shop/app/controllers/shop/items_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Shop + class ItemsController < BaseController + helper_method :items + + private + + def items + @items ||= Shop::Item.active + end + end +end diff --git a/components/shop/app/helpers/admin/shop/item_helper.rb b/components/shop/app/helpers/admin/shop/item_helper.rb new file mode 100644 index 000000000..9c2e7a63e --- /dev/null +++ b/components/shop/app/helpers/admin/shop/item_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Admin + module Shop + module ItemHelper + def item_form_url + params[:action] == 'edit' ? admin_shop_item_path : admin_shop_items_path + end + + def item_form_method + params[:action] == 'edit' ? :put : :post + end + end + end +end diff --git a/components/shop/app/helpers/admin/shop/shop_helper.rb b/components/shop/app/helpers/admin/shop/shop_helper.rb new file mode 100644 index 000000000..8ef75dbe7 --- /dev/null +++ b/components/shop/app/helpers/admin/shop/shop_helper.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Admin + module Shop + module ShopHelper + end + end +end diff --git a/components/shop/app/jobs/shop/application_job.rb b/components/shop/app/jobs/shop/application_job.rb new file mode 100644 index 000000000..062247ce7 --- /dev/null +++ b/components/shop/app/jobs/shop/application_job.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Shop + class ApplicationJob < ActiveJob::Base + end +end diff --git a/components/shop/app/mailers/shop/application_mailer.rb b/components/shop/app/mailers/shop/application_mailer.rb new file mode 100644 index 000000000..1dfbb2361 --- /dev/null +++ b/components/shop/app/mailers/shop/application_mailer.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Shop + class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' + end +end diff --git a/components/shop/app/models/shop/application_record.rb b/components/shop/app/models/shop/application_record.rb new file mode 100644 index 000000000..0a2e3b35c --- /dev/null +++ b/components/shop/app/models/shop/application_record.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Shop + class ApplicationRecord < ::ApplicationRecord + self.abstract_class = true + end +end diff --git a/components/shop/app/models/shop/item.rb b/components/shop/app/models/shop/item.rb new file mode 100644 index 000000000..daa6bdf13 --- /dev/null +++ b/components/shop/app/models/shop/item.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Shop + class Item < ApplicationRecord + self.table_name = 'shop_items' + + has_many :item_images + accepts_nested_attributes_for :item_images + + scope :active, -> { where(published: true) } + + validates :name, presence: true + validates :price, presence: true + validates :available_qty, presence: true + end +end diff --git a/components/shop/app/models/shop/item_image.rb b/components/shop/app/models/shop/item_image.rb new file mode 100644 index 000000000..9d8435b51 --- /dev/null +++ b/components/shop/app/models/shop/item_image.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Shop + class ItemImage < ApplicationRecord + self.table_name = 'shop_item_images' + + belongs_to :item + mount_uploader :image, ItemImageUploader + end +end diff --git a/components/shop/app/uploaders/item_image_uploader.rb b/components/shop/app/uploaders/item_image_uploader.rb new file mode 100644 index 000000000..9e3f8f8ae --- /dev/null +++ b/components/shop/app/uploaders/item_image_uploader.rb @@ -0,0 +1,2 @@ +class ItemImageUploader < CarrierWave::Uploader::Base +end \ No newline at end of file diff --git a/components/shop/app/views/admin/shop/items/form.slim b/components/shop/app/views/admin/shop/items/form.slim new file mode 100644 index 000000000..4f0c907ff --- /dev/null +++ b/components/shop/app/views/admin/shop/items/form.slim @@ -0,0 +1,22 @@ +- title resource_form_text(item, label: :name) + += resource_form_header(item, label: :name) += simple_form_for item, url: item_form_url, method: item_form_method, as: :item do |f| + .ui.grid + .sixteen.wide.field.right-align + = link_to t('words.back'), admin_shop_items_path(item), class: 'ui button grey' + = f.button :submit + + .ui.grid + .sixteen.wide.field = f.input :name + .ui.grid + .sixteen.wide.field = f.input :description + .ui.grid + .six.wide.field = f.input :price + .six.wide.field = f.input :available_qty + .four.wide.field = f.input :published + + = f.simple_fields_for :item_images, Shop::ItemImage.new do |ff| + .fields + .sixteen.wide.field + = ff.input :image, as: :file diff --git a/components/shop/app/views/admin/shop/items/index.slim b/components/shop/app/views/admin/shop/items/index.slim new file mode 100644 index 000000000..a72eb6b0e --- /dev/null +++ b/components/shop/app/views/admin/shop/items/index.slim @@ -0,0 +1,27 @@ +- title t 'shop_items.plural' + += resource_header :shop_item + +table.ui.very.basic.table + thead + tr + th = t 'shop.items.name' + th = t 'shop.items.description' + th = t 'shop.items.price' + th = t 'shop.items.available_qty' + th = t 'shop.items.published' + th = t 'shop.items.img' + th + + tbody + - items.each do |item| + tr + td = item.name + td = item.description + td = item.price + td = item.available_qty + td = item.published + td + = image_tag item.item_images.first.image_url(:small).to_s if item.item_images.first.try(:image_url) + td = controls do + = admin_edit_resource_link(item) diff --git a/components/shop/app/views/shop/items/index.slim b/components/shop/app/views/shop/items/index.slim new file mode 100644 index 000000000..d69d3fb48 --- /dev/null +++ b/components/shop/app/views/shop/items/index.slim @@ -0,0 +1,12 @@ +h2.main-header Shop + +.main + ul.cards + - items.each do |item| + li.cards_item + .card + = image_tag item.item_images.first.image_url(:middle).to_s, class: 'card_image' if item.item_images.first.try(:image_url) + .card_content + h2.card_title = item.name + p.card_text = item.description + button.btn.card_btn Add to cart diff --git a/components/shop/bin/rails b/components/shop/bin/rails new file mode 100755 index 000000000..69462ff26 --- /dev/null +++ b/components/shop/bin/rails @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path('..', __dir__) +ENGINE_PATH = File.expand_path('../lib/shop/engine', __dir__) +APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/components/shop/config/locales/en.shop.yml b/components/shop/config/locales/en.shop.yml new file mode 100644 index 000000000..c3ea722a6 --- /dev/null +++ b/components/shop/config/locales/en.shop.yml @@ -0,0 +1,14 @@ +en: + shop_items: + singular: Item + shop: + singular: Shop + items: + plural: Shop Items + singular: Shop Item + name: Name + description: Description + price: Price + available_qty: Avaliable quantity + published: Published + img: Image diff --git a/components/shop/config/routes.rb b/components/shop/config/routes.rb new file mode 100644 index 000000000..1a826fb9d --- /dev/null +++ b/components/shop/config/routes.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Rails.application.routes.draw do + namespace :shop do + resources :items, only: %i[index] + end + + namespace :admin do + namespace :shop do + resources :items, only: %i[index show new edit create update] + end + end +end diff --git a/components/shop/db/migrate/20210510190241_create_items.rb b/components/shop/db/migrate/20210510190241_create_items.rb new file mode 100644 index 000000000..7cb015c60 --- /dev/null +++ b/components/shop/db/migrate/20210510190241_create_items.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class CreateItems < ActiveRecord::Migration[5.2] + def change + create_table :shop_items do |t| + t.string :name, null: false + t.text :description + t.decimal :price, null: false + t.integer :available_qty, null: false, default: 0 + t.boolean :published, default: false + + t.timestamps + end + end +end diff --git a/components/shop/db/migrate/20210514113103_create_item_images.rb b/components/shop/db/migrate/20210514113103_create_item_images.rb new file mode 100644 index 000000000..c3a24fa2f --- /dev/null +++ b/components/shop/db/migrate/20210514113103_create_item_images.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class CreateItemImages < ActiveRecord::Migration[5.2] + def change + create_table :shop_item_images do |t| + t.string :image + t.references :item + + t.timestamps + end + end +end diff --git a/components/shop/db/seeds.rb b/components/shop/db/seeds.rb new file mode 100644 index 000000000..88f1a0fde --- /dev/null +++ b/components/shop/db/seeds.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +#=== Shop Items ========================================================================= + +puts ::Shop::Item.where(name: 'Pivorak Socks').first_or_create!( + description: 'Test description', price: 12, available_qty: 5 +) diff --git a/components/shop/lib/shop.rb b/components/shop/lib/shop.rb new file mode 100644 index 000000000..1ff62f4eb --- /dev/null +++ b/components/shop/lib/shop.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'shop/engine' + +module Shop + # Your code goes here... +end diff --git a/components/shop/lib/shop/engine.rb b/components/shop/lib/shop/engine.rb new file mode 100644 index 000000000..770c783fa --- /dev/null +++ b/components/shop/lib/shop/engine.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'slim-rails' +require 'kaminari' +require 'simple_form' +require 'friendly_id' +require 'carrierwave' + +module Shop + class Engine < ::Rails::Engine + initializer :append_migrations do |app| + unless app.root.to_s.match(root.to_s) + config.paths['db/migrate'].expanded.each do |p| + app.config.paths['db/migrate'] << p + end + end + end + + initializer 'sample_engine.factories', after: 'factory_bot.set_factory_paths' do + FactoryBot.definition_file_paths << File.expand_path('../../spec/factories', __dir__) if defined?(FactoryBot) + end + end +end diff --git a/components/shop/lib/shop/version.rb b/components/shop/lib/shop/version.rb new file mode 100644 index 000000000..92bb8b3b5 --- /dev/null +++ b/components/shop/lib/shop/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Shop + VERSION = '0.1.0' +end diff --git a/components/shop/lib/tasks/shop_tasks.rake b/components/shop/lib/tasks/shop_tasks.rake new file mode 100644 index 000000000..1f9796b90 --- /dev/null +++ b/components/shop/lib/tasks/shop_tasks.rake @@ -0,0 +1,5 @@ +# frozen_string_literal: true +# desc "Explaining what the task does" +# task :shop do +# # Task goes here +# end diff --git a/components/shop/shop.gemspec b/components/shop/shop.gemspec new file mode 100644 index 000000000..8f747a731 --- /dev/null +++ b/components/shop/shop.gemspec @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +$LOAD_PATH.push File.expand_path('lib', __dir__) + +# Maintain your gem's version: +require 'shop/version' + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |spec| + spec.name = 'shop' + spec.version = Shop::VERSION + spec.authors = ['Vasia Ivanyshak'] + spec.email = ['ivanyshak.vasia@gmail.com'] + spec.homepage = 'https://pivorak.com/' + spec.summary = 'Shop extenstion' + spec.description = 'Shop extenstion' + spec.license = 'MIT' + + # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' + # to allow pushing to a single host or delete this section to allow pushing to any host. + if spec.respond_to?(:metadata) + spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'" + else + raise 'RubyGems 2.0 or newer is required to protect against ' \ + 'public gem pushes.' + end + + spec.files = Dir['{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.md'] + + spec.add_dependency 'rails', '~> 5.2.2', '>= 5.2.2.1' + + spec.add_dependency 'friendly_id' + spec.add_dependency 'kaminari' + spec.add_dependency 'simple_form' + spec.add_dependency 'slim-rails' + spec.add_dependency 'carrierwave', '~> 1.2' + + spec.add_development_dependency 'capybara' + spec.add_development_dependency 'faker' + spec.add_development_dependency 'guard-rspec' + spec.add_development_dependency 'launchy' + spec.add_development_dependency 'pry-rails' + spec.add_development_dependency 'rspec-rails' + spec.add_development_dependency 'simplecov' + + spec.add_development_dependency 'factory_bot_rails' + spec.add_development_dependency 'sqlite3' +end diff --git a/components/shop/spec/dummy/.ruby-version b/components/shop/spec/dummy/.ruby-version new file mode 100644 index 000000000..a7b149191 --- /dev/null +++ b/components/shop/spec/dummy/.ruby-version @@ -0,0 +1 @@ +ruby-2.6.5 \ No newline at end of file diff --git a/components/shop/spec/dummy/Rakefile b/components/shop/spec/dummy/Rakefile new file mode 100644 index 000000000..488c551fe --- /dev/null +++ b/components/shop/spec/dummy/Rakefile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/components/shop/spec/dummy/app/assets/config/manifest.js b/components/shop/spec/dummy/app/assets/config/manifest.js new file mode 100644 index 000000000..7a89f4c98 --- /dev/null +++ b/components/shop/spec/dummy/app/assets/config/manifest.js @@ -0,0 +1,4 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css +//= link shop_manifest.js diff --git a/components/shop/spec/dummy/app/assets/images/.keep b/components/shop/spec/dummy/app/assets/images/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/assets/javascripts/application.js b/components/shop/spec/dummy/app/assets/javascripts/application.js new file mode 100644 index 000000000..67ce4675c --- /dev/null +++ b/components/shop/spec/dummy/app/assets/javascripts/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require rails-ujs +//= require activestorage +//= require_tree . diff --git a/components/shop/spec/dummy/app/assets/javascripts/cable.js b/components/shop/spec/dummy/app/assets/javascripts/cable.js new file mode 100644 index 000000000..739aa5f02 --- /dev/null +++ b/components/shop/spec/dummy/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `rails generate channel` command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/components/shop/spec/dummy/app/assets/javascripts/channels/.keep b/components/shop/spec/dummy/app/assets/javascripts/channels/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/assets/stylesheets/application.css b/components/shop/spec/dummy/app/assets/stylesheets/application.css new file mode 100644 index 000000000..0ebd7fe82 --- /dev/null +++ b/components/shop/spec/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/components/shop/spec/dummy/app/controllers/admin/base_controller.rb b/components/shop/spec/dummy/app/controllers/admin/base_controller.rb new file mode 100644 index 000000000..8d1ea4223 --- /dev/null +++ b/components/shop/spec/dummy/app/controllers/admin/base_controller.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +# Mock of original controller +module Admin + class BaseController < ApplicationController + helper_method :current_user, :line_chart + + def self.add_breadcrumb(*); end + + def line_chart(*); end + + def edit + render_form + end + + def current_user + User.find_or_create_by(email: 'test@test.com', first_name: 'Test', last_name: 'User') + end + + private + + def render_form + render :form + end + + def semantic_breadcrumb(*); end + + def add_breadcrumb(resource, label: :title, path: nil) + if resource.instance_of?(String) + semantic_breadcrumb I18n.t(resource), path + else + semantic_breadcrumb resource.send(label), path + end + end + + def add_new_breadcump + add_breadcrumb 'words.new' + end + + def add_edit_breadcump + add_breadcrumb 'words.edit' + end + + def react_to(action) + if action + flash_success && default_redirect + else + flash_error && render_form + end + end + + def flash_success(key = nil) + add_flash(:success, key) + end + + def flash_error(key = nil) + add_flash(:error, key) + end + + def add_flash(type, key = nil) + resource = params[:controller].split('/').last.singularize.capitalize + suffix = params[:action] == 'destroy' ? 'ed' : 'd' + action = "#{params[:action]}#{suffix}" + + flash[type] = t(key || type, scope: :notifications, resource: resource, action: action) + end + + def current_user + @current_user ||= User.where(id: 1).first_or_create(email: 'test@user.com', first_name: 'Test', last_name: 'User') + end + end +end diff --git a/components/shop/spec/dummy/app/controllers/application_controller.rb b/components/shop/spec/dummy/app/controllers/application_controller.rb new file mode 100644 index 000000000..acc2fbad8 --- /dev/null +++ b/components/shop/spec/dummy/app/controllers/application_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + def authenticate_user!; end + + def flash_success + true + end + + def flash_error + true + end + + def current_user + User.find_or_create_by(email: 'test@test.com', first_name: 'Test', last_name: 'User') + end +end diff --git a/components/shop/spec/dummy/app/controllers/concerns/.keep b/components/shop/spec/dummy/app/controllers/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/helpers/application_helper.rb b/components/shop/spec/dummy/app/helpers/application_helper.rb new file mode 100644 index 000000000..9f0723975 --- /dev/null +++ b/components/shop/spec/dummy/app/helpers/application_helper.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Mocks +module ApplicationHelper + def title(*); end + + def resource_header(*); end + + def format_timestamp(*); end + + def bool_icon(*); end + + def controls(*); end + + def resource_form_text(*); end + + def resource_form_header(*); end + + def admin_back_link(*); end + + def icon(*); end +end diff --git a/components/shop/spec/dummy/app/jobs/application_job.rb b/components/shop/spec/dummy/app/jobs/application_job.rb new file mode 100644 index 000000000..d92ffddcb --- /dev/null +++ b/components/shop/spec/dummy/app/jobs/application_job.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class ApplicationJob < ActiveJob::Base +end diff --git a/components/shop/spec/dummy/app/mailers/application_mailer.rb b/components/shop/spec/dummy/app/mailers/application_mailer.rb new file mode 100644 index 000000000..d84cb6e71 --- /dev/null +++ b/components/shop/spec/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/components/shop/spec/dummy/app/models/application_record.rb b/components/shop/spec/dummy/app/models/application_record.rb new file mode 100644 index 000000000..71fbba5b3 --- /dev/null +++ b/components/shop/spec/dummy/app/models/application_record.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/components/shop/spec/dummy/app/models/concerns/.keep b/components/shop/spec/dummy/app/models/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/bin/bundle b/components/shop/spec/dummy/bin/bundle new file mode 100755 index 000000000..2dbb71769 --- /dev/null +++ b/components/shop/spec/dummy/bin/bundle @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/components/shop/spec/dummy/bin/rails b/components/shop/spec/dummy/bin/rails new file mode 100755 index 000000000..a31728ab9 --- /dev/null +++ b/components/shop/spec/dummy/bin/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/components/shop/spec/dummy/bin/rake b/components/shop/spec/dummy/bin/rake new file mode 100755 index 000000000..c19995500 --- /dev/null +++ b/components/shop/spec/dummy/bin/rake @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/components/shop/spec/dummy/bin/setup b/components/shop/spec/dummy/bin/setup new file mode 100755 index 000000000..5068a6b28 --- /dev/null +++ b/components/shop/spec/dummy/bin/setup @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/MixinUsage +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end +# rubocop:enable Style/MixinUsage diff --git a/components/shop/spec/dummy/bin/update b/components/shop/spec/dummy/bin/update new file mode 100755 index 000000000..4f0680e8d --- /dev/null +++ b/components/shop/spec/dummy/bin/update @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/MixinUsage +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end +# rubocop:enable Style/MixinUsage diff --git a/components/shop/spec/dummy/bin/yarn b/components/shop/spec/dummy/bin/yarn new file mode 100755 index 000000000..4cac416a1 --- /dev/null +++ b/components/shop/spec/dummy/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + exec 'yarnpkg', *ARGV +rescue Errno::ENOENT + warn 'Yarn executable was not detected in the system.' + warn 'Download Yarn at https://yarnpkg.com/en/docs/install' + exit 1 +end diff --git a/components/shop/spec/dummy/config.ru b/components/shop/spec/dummy/config.ru new file mode 100644 index 000000000..842bccc34 --- /dev/null +++ b/components/shop/spec/dummy/config.ru @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/components/shop/spec/dummy/config/application.rb b/components/shop/spec/dummy/config/application.rb new file mode 100644 index 000000000..09a12e02a --- /dev/null +++ b/components/shop/spec/dummy/config/application.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require_relative 'boot' + +require 'rails/all' + +Bundler.require(*Rails.groups) +require 'shop' + +module Dummy + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.2 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. + end +end diff --git a/components/shop/spec/dummy/config/boot.rb b/components/shop/spec/dummy/config/boot.rb new file mode 100644 index 000000000..6d2cba07a --- /dev/null +++ b/components/shop/spec/dummy/config/boot.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) diff --git a/components/shop/spec/dummy/config/cable.yml b/components/shop/spec/dummy/config/cable.yml new file mode 100644 index 000000000..1cd0f8363 --- /dev/null +++ b/components/shop/spec/dummy/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: dummy_production diff --git a/components/shop/spec/dummy/config/database.yml b/components/shop/spec/dummy/config/database.yml new file mode 100644 index 000000000..0d02f2498 --- /dev/null +++ b/components/shop/spec/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/components/shop/spec/dummy/config/environment.rb b/components/shop/spec/dummy/config/environment.rb new file mode 100644 index 000000000..d5abe5580 --- /dev/null +++ b/components/shop/spec/dummy/config/environment.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/components/shop/spec/dummy/config/environments/development.rb b/components/shop/spec/dummy/config/environments/development.rb new file mode 100644 index 000000000..da0edff2b --- /dev/null +++ b/components/shop/spec/dummy/config/environments/development.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/components/shop/spec/dummy/config/environments/production.rb b/components/shop/spec/dummy/config/environments/production.rb new file mode 100644 index 000000000..d8767a110 --- /dev/null +++ b/components/shop/spec/dummy/config/environments/production.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_#{Rails.env}" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV['RAILS_LOG_TO_STDOUT'].present? + logger = ActiveSupport::Logger.new($stdout) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/components/shop/spec/dummy/config/environments/test.rb b/components/shop/spec/dummy/config/environments/test.rb new file mode 100644 index 000000000..53a6653e6 --- /dev/null +++ b/components/shop/spec/dummy/config/environments/test.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # I am very proud of this WORKAROUND! :) + config.paths['db/migrate'] << Shop::Engine.root.join('db', 'migrate').to_s + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb b/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb new file mode 100644 index 000000000..f4556db39 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/components/shop/spec/dummy/config/initializers/assets.rb b/components/shop/spec/dummy/config/initializers/assets.rb new file mode 100644 index 000000000..a9b0d0f10 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/assets.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb b/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 000000000..d0f0d3b5d --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/components/shop/spec/dummy/config/initializers/content_security_policy.rb b/components/shop/spec/dummy/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..497f5667c --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/content_security_policy.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/components/shop/spec/dummy/config/initializers/cookies_serializer.rb b/components/shop/spec/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 000000000..ee8dff9c9 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb b/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..7a4f47b4c --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/components/shop/spec/dummy/config/initializers/inflections.rb b/components/shop/spec/dummy/config/initializers/inflections.rb new file mode 100644 index 000000000..aa7435fbc --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/inflections.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/components/shop/spec/dummy/config/initializers/mime_types.rb b/components/shop/spec/dummy/config/initializers/mime_types.rb new file mode 100644 index 000000000..6e1d16f02 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/components/shop/spec/dummy/config/initializers/wrap_parameters.rb b/components/shop/spec/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 000000000..2f3c0db47 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/components/shop/spec/dummy/config/locales/en.yml b/components/shop/spec/dummy/config/locales/en.yml new file mode 100644 index 000000000..decc5a857 --- /dev/null +++ b/components/shop/spec/dummy/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/components/shop/spec/dummy/config/puma.rb b/components/shop/spec/dummy/config/puma.rb new file mode 100644 index 000000000..d9a94f35d --- /dev/null +++ b/components/shop/spec/dummy/config/puma.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch('PORT', 3000) + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch('RAILS_ENV', 'development') + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/components/shop/spec/dummy/config/routes.rb b/components/shop/spec/dummy/config/routes.rb new file mode 100644 index 000000000..edf04d2d6 --- /dev/null +++ b/components/shop/spec/dummy/config/routes.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +Rails.application.routes.draw do +end diff --git a/components/shop/spec/dummy/config/spring.rb b/components/shop/spec/dummy/config/spring.rb new file mode 100644 index 000000000..c5933e491 --- /dev/null +++ b/components/shop/spec/dummy/config/spring.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +%w[ + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +].each { |path| Spring.watch(path) } diff --git a/components/shop/spec/dummy/config/storage.yml b/components/shop/spec/dummy/config/storage.yml new file mode 100644 index 000000000..d32f76e8f --- /dev/null +++ b/components/shop/spec/dummy/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/components/shop/spec/dummy/db/schema.rb b/components/shop/spec/dummy/db/schema.rb new file mode 100644 index 000000000..285f33b28 --- /dev/null +++ b/components/shop/spec/dummy/db/schema.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20_210_514_113_103) do + create_table 'shop_item_images', force: :cascade do |t| + t.string 'image' + t.integer 'item_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['item_id'], name: 'index_shop_item_images_on_item_id' + end + + create_table 'shop_items', force: :cascade do |t| + t.string 'name', null: false + t.text 'description' + t.decimal 'price', null: false + t.integer 'available_qty', default: 0, null: false + t.boolean 'published', default: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + end +end diff --git a/components/shop/spec/dummy/lib/assets/.keep b/components/shop/spec/dummy/lib/assets/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/log/.keep b/components/shop/spec/dummy/log/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/package.json b/components/shop/spec/dummy/package.json new file mode 100644 index 000000000..caa2d7bb3 --- /dev/null +++ b/components/shop/spec/dummy/package.json @@ -0,0 +1,5 @@ +{ + "name": "dummy", + "private": true, + "dependencies": {} +} diff --git a/components/shop/spec/dummy/public/404.html b/components/shop/spec/dummy/public/404.html new file mode 100644 index 000000000..2be3af26f --- /dev/null +++ b/components/shop/spec/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/components/shop/spec/dummy/public/422.html b/components/shop/spec/dummy/public/422.html new file mode 100644 index 000000000..c08eac0d1 --- /dev/null +++ b/components/shop/spec/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/components/shop/spec/dummy/public/500.html b/components/shop/spec/dummy/public/500.html new file mode 100644 index 000000000..78a030af2 --- /dev/null +++ b/components/shop/spec/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/components/shop/spec/dummy/public/apple-touch-icon-precomposed.png b/components/shop/spec/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/public/apple-touch-icon.png b/components/shop/spec/dummy/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/public/favicon.ico b/components/shop/spec/dummy/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/factories/item_factory.rb b/components/shop/spec/factories/item_factory.rb new file mode 100644 index 000000000..4b5194065 --- /dev/null +++ b/components/shop/spec/factories/item_factory.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :item, class: Shop::Item do + name { Faker::Lorem.word } + description { Faker::Lorem.word } + price { 12 } + end +end diff --git a/components/shop/spec/features/admin/shop/items/create_spec.rb b/components/shop/spec/features/admin/shop/items/create_spec.rb new file mode 100644 index 000000000..954a596c3 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/create_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Shop Item CREATE' do + let!(:shop_item) { create(:item, published: true) } + let(:new_shop_item_path) { '/admin/shop/items/new' } + + before { visit new_shop_item_path } + + describe 'invalid input' do + context 'name is not present' do + it 'validates errors' do + shop_item.name = '' + + expect(shop_item).not_to be_valid + end + end + + context 'price nil' do + it 'validates errors' do + shop_item.price = nil + + expect(shop_item).not_to be_valid + end + end + + context 'available_qty nil' do + it 'validates errors' do + shop_item.available_qty = nil + + expect(shop_item).not_to be_valid + end + end + end + + context 'valid input' do + it 'creates item' do + fill_in 'Name', with: 'Pivorak Socks' + fill_in 'Description', with: 'Very hard interview' + fill_in 'Price', with: 5 + fill_in 'Available qty', with: 10 + check 'Published' + click_button 'Create Item' + + expect(page).to have_current_path '/admin/shop/items' + expect(page).to have_content 'Pivorak Socks' + end + end +end diff --git a/components/shop/spec/features/admin/shop/items/list_spec.rb b/components/shop/spec/features/admin/shop/items/list_spec.rb new file mode 100644 index 000000000..baecfe936 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/list_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Admin Shop Items LIST' do + let!(:active_item) { create(:item, published: true) } + + scenario 'display items' do + visit '/admin/shop/items' + + expect(page).to have_content active_item.name + end +end diff --git a/components/shop/spec/features/admin/shop/items/update_spec.rb b/components/shop/spec/features/admin/shop/items/update_spec.rb new file mode 100644 index 000000000..9bbbfe566 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/update_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Shop Item UPDATE' do + let!(:shop_item) { create(:item, published: true) } + let(:edit_shop_item_path) { '/admin/shop/items/1/edit' } + + before { visit edit_shop_item_path } + + context 'invalid input' do + it 'validates errors' do + fill_in 'Name', with: '' + click_button 'Update Item' + + expect_an_error item_name: :blank + end + end + + context 'valid input' do + it 'update season' do + fill_in 'Name', with: 'Best Socks' + click_button 'Update Item' + + expect(page).to have_current_path '/admin/shop/items' + expect(page).to have_content 'Best Socks' + end + end +end diff --git a/components/shop/spec/features/shop/add_to_cart_spec.rb b/components/shop/spec/features/shop/add_to_cart_spec.rb new file mode 100644 index 000000000..5179920ef --- /dev/null +++ b/components/shop/spec/features/shop/add_to_cart_spec.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: true +# TODO diff --git a/components/shop/spec/features/shop/checkout_spec.rb b/components/shop/spec/features/shop/checkout_spec.rb new file mode 100644 index 000000000..daa77a0c8 --- /dev/null +++ b/components/shop/spec/features/shop/checkout_spec.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +# TODO + +# 1. Shipping +# 2. Payment +# 3. Place order diff --git a/components/shop/spec/features/shop/home_page_spec.rb b/components/shop/spec/features/shop/home_page_spec.rb new file mode 100644 index 000000000..c7ff126f1 --- /dev/null +++ b/components/shop/spec/features/shop/home_page_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe '/shop' do + context 'success' do + let!(:item_a) { create(:item, published: true) } + let!(:item_b) { create(:item, published: false) } + + scenario 'display items' do + visit admin_shop_items_path + + expect(page).to have_content item_a.name + expect(page).to have_content item_b.name + end + end +end diff --git a/components/shop/spec/features/shop/shopping_cart_spec.rb b/components/shop/spec/features/shop/shopping_cart_spec.rb new file mode 100644 index 000000000..464090415 --- /dev/null +++ b/components/shop/spec/features/shop/shopping_cart_spec.rb @@ -0,0 +1 @@ +# TODO diff --git a/components/shop/spec/fixtures/items.yml b/components/shop/spec/fixtures/items.yml new file mode 100644 index 000000000..a33d0e06b --- /dev/null +++ b/components/shop/spec/fixtures/items.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 + +two: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 diff --git a/components/shop/spec/fixtures/shop/items.yml b/components/shop/spec/fixtures/shop/items.yml new file mode 100644 index 000000000..a33d0e06b --- /dev/null +++ b/components/shop/spec/fixtures/shop/items.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 + +two: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 diff --git a/components/shop/spec/integration/navigation_test.rb b/components/shop/spec/integration/navigation_test.rb new file mode 100644 index 000000000..91d920fb6 --- /dev/null +++ b/components/shop/spec/integration/navigation_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class NavigationTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/components/shop/spec/models/item_test.rb b/components/shop/spec/models/item_test.rb new file mode 100644 index 000000000..2a464381b --- /dev/null +++ b/components/shop/spec/models/item_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ItemTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/components/shop/spec/models/shop/item_spec.rb b/components/shop/spec/models/shop/item_spec.rb new file mode 100644 index 000000000..98eb69fc3 --- /dev/null +++ b/components/shop/spec/models/shop/item_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Shop::Item, type: :model do + describe 'validations' do + context 'when item valid' do + subject { build(:item) } + + it 'is valid with valid attributes' do + expect(subject).to be_valid + end + end + + context 'when name missing' do + subject { build(:item, name: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + + context 'when available_qty missing' do + subject { build(:item, available_qty: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + + context 'when available_qty price' do + subject { build(:item, price: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + end +end diff --git a/components/shop/spec/models/shop/item_test.rb b/components/shop/spec/models/shop/item_test.rb new file mode 100644 index 000000000..973102e2a --- /dev/null +++ b/components/shop/spec/models/shop/item_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Shop + class ItemTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end + end +end diff --git a/components/shop/spec/rails_helper.rb b/components/shop/spec/rails_helper.rb new file mode 100644 index 000000000..c8dd88cbe --- /dev/null +++ b/components/shop/spec/rails_helper.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' + +require File.expand_path('../spec/dummy/config/environment', __dir__) + +abort('The Rails environment is running in production mode!') if Rails.env.production? + +require 'rspec/rails' +require 'pry-rails' +require 'capybara/rails' +require 'factory_bot_rails' +require 'faker' + +Dir[Shop::Engine.root.join('spec/support/*.rb')].sort.each { |f| require f } + +ActiveRecord::Migration.maintain_test_schema! + +Dir['../spec/support/**/*.rb'].sort.each { |f| require f } + +RSpec.configure do |config| + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! + config.filter_rails_from_backtrace! + + config.include FactoryBot::Syntax::Methods + config.include Shop::Test::FeaturesHelpers, type: :feature +end diff --git a/components/shop/spec/shop_test.rb b/components/shop/spec/shop_test.rb new file mode 100644 index 000000000..7e06e60dc --- /dev/null +++ b/components/shop/spec/shop_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Shop + class Test < ActiveSupport::TestCase + test 'truth' do + assert_kind_of Module, Shop + end + end +end diff --git a/components/shop/spec/spec_helper.rb b/components/shop/spec/spec_helper.rb new file mode 100644 index 000000000..c0fc188e4 --- /dev/null +++ b/components/shop/spec/spec_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'pry' +require 'simplecov' +SimpleCov.start 'rails' + +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups + + config.filter_run_when_matching :focus +end diff --git a/components/shop/spec/support/features_helpers.rb b/components/shop/spec/support/features_helpers.rb new file mode 100644 index 000000000..2d087dbf2 --- /dev/null +++ b/components/shop/spec/support/features_helpers.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Shop + module Test + module FeaturesHelpers + # + # Validation errors + # + def expect_an_error(hash_pair = {}, nope = false) + field = hash_pair.keys.first + value = hash_pair.values.first + error_div = "div.#{field}.field_with_errors" + + msg = case value + when :blank + "can't be blank" + when :has_been_taken + 'has already been taken' + else + value + end + + to_or_not = nope ? :not_to : :to + + expect(page).send(to_or_not, have_css(error_div)) + + return if nope + + expect(find(error_div.to_s)).send(to_or_not, have_content(msg)) + end + + def expect_not_an_error(hash_pair = {}) + expect_an_error(hash_pair, true) + end + + # + # Flash errors + # + def expect_success_flash_message(resource, action) + expect(page).to have_content "#{resource} has been successfully #{action}" + end + + # Error + def expect_error_flash_message(resource, action) + expect(page).to have_content "#{resource} cannot be #{action}. Please check the errors below" + end + end + end +end diff --git a/components/shop/spec/test_helper.rb b/components/shop/spec/test_helper.rb new file mode 100644 index 000000000..ea8ed4b61 --- /dev/null +++ b/components/shop/spec/test_helper.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# Configure Rails Environment +ENV['RAILS_ENV'] = 'test' + +require_relative '../test/dummy/config/environment' +ActiveRecord::Migrator.migrations_paths = [File.expand_path('../test/dummy/db/migrate', __dir__)] +ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __dir__) +require 'rails/test_help' + +# Filter out Minitest backtrace while allowing backtrace from other libraries +# to be shown. +Minitest.backtrace_filter = Minitest::BacktraceFilter.new + +# Load fixtures from the engine +if ActiveSupport::TestCase.respond_to?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = File.expand_path('fixtures', __dir__) + ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path + ActiveSupport::TestCase.file_fixture_path = "#{ActiveSupport::TestCase.fixture_path}/files" + ActiveSupport::TestCase.fixtures :all +end diff --git a/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb b/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb index de3a577a4..203fa78f1 100644 --- a/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb +++ b/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb @@ -5,7 +5,6 @@ def up EmailTemplate.create!( title: 'VisitRequestMailer#attendance_confirmed', subject: 'Thanks for confirming your visit', - note: 'Will be sent when attendee answers YES in the final confirmation message', body: File.read('db/seed/email_templates/attendance_confirmed.md') ) end diff --git a/db/schema.rb b/db/schema.rb index 99735d843..dd483650b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_03_30_085332) do +ActiveRecord::Schema.define(version: 2021_05_14_113103) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -234,6 +234,24 @@ t.index ["user_id"], name: "index_season_mentors_on_user_id" end + create_table "shop_item_images", force: :cascade do |t| + t.string "image" + t.bigint "item_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["item_id"], name: "index_shop_item_images_on_item_id" + end + + create_table "shop_items", force: :cascade do |t| + t.string "name", null: false + t.text "description" + t.decimal "price", null: false + t.integer "available_qty", default: 0, null: false + t.boolean "published", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "taggings", id: :serial, force: :cascade do |t| t.integer "tag_id" t.string "taggable_type" diff --git a/db/seeds.rb b/db/seeds.rb index 82c0c6187..ce397a2f3 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -84,3 +84,5 @@ puts '==== Courses seeds ====' Courses::Engine.load_seed + +Shop::Engine.load_seed