Compare commits

..

5 Commits

Author SHA1 Message Date
Mohamed ABDELLANI
1c60a3a660 read rendering options directly from the model ReportRendingOptions 2022-11-16 12:40:02 +01:00
Mohamed ABDELLANI
ac7a7b11a5 store display_header_row flag in the model 2022-11-16 12:29:44 +01:00
Mohamed ABDELLANI
0fb273ce93 store display_summary_row in the model 2022-11-16 12:27:52 +01:00
Mohamed ABDELLANI
709dfa42bc load fields_to_show from DB when user access the report 2022-11-16 12:08:32 +01:00
Mohamed ABDELLANI
9561140466 create ReportRenderingOptions model 2022-11-16 12:02:47 +01:00
93 changed files with 875 additions and 1806 deletions

View File

@@ -8,7 +8,7 @@ on:
pull_request:
env:
DISABLE_KNAPSACK_PRO: false
DISABLE_KNAPSACK: true
TIMEZONE: UTC
COVERAGE: true
RAILS_ENV: test
@@ -17,7 +17,7 @@ permissions:
contents: read
jobs:
knapsack_rspec_controllers:
rspec:
runs-on: ubuntu-20.04
services:
postgres:
@@ -33,15 +33,19 @@ jobs:
POSTGRES_USER: ofn
POSTGRES_PASSWORD: f00d
strategy:
fail-fast: false
matrix:
# [n] - where the n is a number of parallel jobs you want to run your tests on.
# Use a higher number if you have slow tests to split them between more parallel jobs.
# Remember to update the value of the `ci_node_index` below to (0..n-1).
ci_node_total: [8]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7]
specs:
- "spec/controllers"
- "spec/models"
- "spec/lib"
- "spec/migrations"
- "spec/serializers"
- "spec/system/admin/[a-o0-9]*"
- "spec/system/admin/[p-z]*"
- "spec/system/consumer/[a-o0-9]*"
- "spec/system/consumer/[p-z]*"
- "engines/*/spec"
fail-fast: false
steps:
- uses: actions/checkout@v3
@@ -68,161 +72,7 @@ jobs:
bundle exec rake db:schema:load
- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: 864ef557d85ea8e603e086c0387d5154
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
KNAPSACK_PRO_LOG_LEVEL: info
# if you use Knapsack Pro Queue Mode you must set below env variable
# to be able to retry CI build and run previously recorded tests
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
# KNAPSACK_PRO_FIXED_QUEUE_SPLIT: false
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
run: |
bundle exec rake knapsack_pro:rspec
knapsack_rspec_models:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:10
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
POSTGRES_DB: open_food_network_test
POSTGRES_USER: ofn
POSTGRES_PASSWORD: f00d
strategy:
fail-fast: false
matrix:
# [n] - where the n is a number of parallel jobs you want to run your tests on.
# Use a higher number if you have slow tests to split them between more parallel jobs.
# Remember to update the value of the `ci_node_index` below to (0..n-1).
ci_node_total: [7]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4, 5, 6]
steps:
- uses: actions/checkout@v3
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
redis-version: 6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install JS dependencies
run: yarn install --frozen-lockfile
- name: Set up database
run: |
bundle exec rake db:create
bundle exec rake db:schema:load
- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: 09476e2ce491c12083df62768667c674
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
KNAPSACK_PRO_LOG_LEVEL: info
# if you use Knapsack Pro Queue Mode you must set below env variable
# to be able to retry CI build and run previously recorded tests
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
# KNAPSACK_PRO_FIXED_QUEUE_SPLIT: false
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
run: |
bundle exec rake knapsack_pro:rspec
knapsack_rspec_system:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:10
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
POSTGRES_DB: open_food_network_test
POSTGRES_USER: ofn
POSTGRES_PASSWORD: f00d
strategy:
fail-fast: false
matrix:
# [n] - where the n is a number of parallel jobs you want to run your tests on.
# Use a higher number if you have slow tests to split them between more parallel jobs.
# Remember to update the value of the `ci_node_index` below to (0..n-1).
ci_node_total: [10]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
steps:
- uses: actions/checkout@v3
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
redis-version: 6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install JS dependencies
run: yarn install --frozen-lockfile
- name: Set up database
run: |
bundle exec rake db:create
bundle exec rake db:schema:load
- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: ff2456e64c9f2aa5157eb0daf711d3c3
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
KNAPSACK_PRO_LOG_LEVEL: info
# if you use Knapsack Pro Queue Mode you must set below env variable
# to be able to retry CI build and run previously recorded tests
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
KNAPSACK_PRO_FIXED_QUEUE_SPLIT: true
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/**/*_spec.rb}"
run: |
bundle exec rake knapsack_pro:queue:rspec
run: bundle exec rspec --profile -- ${{ matrix.specs }}
- name: Archive failed tests screenshots
if: failure()
@@ -233,155 +83,7 @@ jobs:
retention-days: 7
if-no-files-found: ignore
knapsack_rspec_engines:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:10
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
POSTGRES_DB: open_food_network_test
POSTGRES_USER: ofn
POSTGRES_PASSWORD: f00d
strategy:
fail-fast: false
matrix:
# [n] - where the n is a number of parallel jobs you want to run your tests on.
# Use a higher number if you have slow tests to split them between more parallel jobs.
# Remember to update the value of the `ci_node_index` below to (0..n-1).
ci_node_total: [5]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
redis-version: 6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install JS dependencies
run: yarn install --frozen-lockfile
- name: Set up database
run: |
bundle exec rake db:create
bundle exec rake db:schema:load
- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: d6ea7ceb766404ccd016c19aa2c81b1c
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
KNAPSACK_PRO_LOG_LEVEL: info
# if you use Knapsack Pro Queue Mode you must set below env variable
# to be able to retry CI build and run previously recorded tests
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
# KNAPSACK_PRO_FIXED_QUEUE_SPLIT: false
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/serializers/**/*_spec.rb,engines/**/*_spec.rb}"
run: |
bundle exec rake knapsack_pro:rspec
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: failed-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
knapsack_rspec_test_the_rest:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:10
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
POSTGRES_DB: open_food_network_test
POSTGRES_USER: ofn
POSTGRES_PASSWORD: f00d
strategy:
fail-fast: false
matrix:
# [n] - where the n is a number of parallel jobs you want to run your tests on.
# Use a higher number if you have slow tests to split them between more parallel jobs.
# Remember to update the value of the `ci_node_index` below to (0..n-1).
ci_node_total: [5]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
redis-version: 6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install JS dependencies
run: yarn install --frozen-lockfile
- name: Set up database
run: |
bundle exec rake db:create
bundle exec rake db:schema:load
- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: e3b8800198d2d89b70c7edbdd85f8fd8
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
KNAPSACK_PRO_LOG_LEVEL: info
# if you use Knapsack Pro Queue Mode you must set below env variable
# to be able to retry CI build and run previously recorded tests
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
# KNAPSACK_PRO_FIXED_QUEUE_SPLIT: false
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN: "{engines/**/*_spec.rb,spec/models/**/*_spec.rb,spec/controllers/**/*_spec.rb,spec/serializers/**/*_spec.rb,spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/system/**/*_spec.rb}"
run: |
bundle exec rake knapsack_pro:rspec
non_knapsack_jest_karma:
test-the-rest:
runs-on: ubuntu-20.04
services:
postgres:
@@ -420,8 +122,12 @@ jobs:
run: |
bundle exec rake db:create
bundle exec rake db:schema:load
- name: Run JS tests
run: bundle exec rake karma:run
- name: Run jest tests
run: yarn jest
- name: Run all other tests
run: bundle exec rake ofn:specs:run:excluding_folders["models,controllers,serializers,features,lib,migrations,system"]

View File

@@ -1,8 +1,6 @@
# Basically, ignore everythings expect app/webpacker/controllers/*.js and app/webpacker/packs/*.js
*.css
*.scss
# Except v2
!/app/webpacker/css/admin/v2/**/*.scss
*.md
*.yml
*.yaml

View File

@@ -83,7 +83,7 @@ Then the main application tests can be run with:
The tests of all custom engines can be run with:
bundle exec rspec ./engines
bundle exec rake ofn:specs:engines:rspec
Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop.

View File

@@ -136,8 +136,6 @@ gem 'flipper-ui'
gem "view_component"
gem 'mini_portile2', '~> 2.8'
group :production, :staging do
gem 'ddtrace'
gem 'rack-timeout'
@@ -152,7 +150,7 @@ group :test, :development do
gem "factory_bot_rails", '6.2.0', require: false
gem 'fuubar', '~> 2.5.1'
gem 'json_spec', '~> 1.1.4'
gem 'knapsack_pro'
gem 'knapsack', require: false
gem 'letter_opener', '>= 1.4.1'
gem 'rspec-rails', ">= 3.5.2"
gem 'rspec-retry', require: false
@@ -166,6 +164,7 @@ group :test do
gem 'pdf-reader'
gem 'rails-controller-testing'
gem 'simplecov', require: false
gem 'test-prof', require: false
gem 'vcr', require: false
gem 'webmock', require: false
# See spec/spec_helper.rb for instructions

View File

@@ -158,16 +158,16 @@ GEM
awesome_nested_set (3.5.0)
activerecord (>= 4.0.0, < 7.1)
aws-eventstream (1.2.0)
aws-partitions (1.669.0)
aws-sdk-core (3.168.2)
aws-partitions (1.651.0)
aws-sdk-core (3.166.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.60.0)
aws-sdk-kms (1.59.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.117.2)
aws-sdk-s3 (1.117.1)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
@@ -177,12 +177,12 @@ GEM
bigdecimal (3.0.2)
bindata (2.4.12)
bindex (0.8.1)
bootsnap (1.15.0)
bootsnap (1.13.0)
msgpack (~> 1.2)
bugsnag (6.25.0)
bugsnag (6.24.2)
concurrent-ruby (~> 1.0)
builder (3.2.4)
bullet (7.0.4)
bullet (7.0.3)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
cable_ready (5.0.0.pre9)
@@ -210,6 +210,7 @@ GEM
rubyzip (>= 1.3.0, < 3)
choice (0.2.0)
chronic (0.10.2)
cliver (0.3.2)
coderay (1.1.3)
coffee-rails (5.0.0)
coffee-script (>= 2.2.0)
@@ -228,9 +229,9 @@ GEM
crass (1.0.6)
css_parser (1.11.0)
addressable
cuprite (0.14.3)
capybara (~> 3.0)
ferrum (~> 0.13.0)
cuprite (0.13)
capybara (>= 2.1, < 4)
ferrum (~> 0.11.0)
database_cleaner (2.0.1)
database_cleaner-active_record (~> 2.0.0)
database_cleaner-active_record (2.0.0)
@@ -241,8 +242,8 @@ GEM
debase-ruby_core_source (= 0.10.12)
msgpack
debase-ruby_core_source (0.10.12)
debug (1.7.0)
irb (>= 1.5.0)
debug (1.6.3)
irb (>= 1.3.6)
reline (>= 0.3.1)
debugger-linecache (1.2.0)
devise (4.8.1)
@@ -258,7 +259,7 @@ GEM
devise-token_authenticatable (1.1.0)
devise (>= 4.0.0, < 5.0.0)
diff-lcs (1.5.0)
digest (3.1.1)
digest (3.1.0)
docile (1.4.0)
dotenv (2.8.1)
dotenv-rails (2.8.1)
@@ -280,10 +281,10 @@ GEM
faraday-follow_redirects (0.3.0)
faraday (>= 1, < 3)
faraday-net_http (3.0.1)
ferrum (0.13)
ferrum (0.11)
addressable (~> 2.5)
cliver (~> 0.3)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8)
ffaker (2.21.0)
ffi (1.15.5)
@@ -351,16 +352,16 @@ GEM
activerecord (>= 3.0)
io-console (0.5.11)
ipaddress (0.8.3)
irb (1.5.1)
irb (1.4.2)
reline (>= 0.3.0)
jmespath (1.6.2)
jmespath (1.6.1)
jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (4.2.1)
railties (>= 3.2.16)
json (2.6.3)
json (2.6.2)
json-jwt (1.16.0)
activesupport (>= 4.2)
aes_key_wrap
@@ -375,7 +376,7 @@ GEM
jsonapi-serializer (2.2.0)
activesupport (>= 4.2)
jwt (2.5.0)
knapsack_pro (3.5.0)
knapsack (4.0.0)
rake
launchy (2.5.0)
addressable (~> 2.7)
@@ -409,7 +410,7 @@ GEM
money (~> 6.12)
money (6.16.0)
i18n (>= 0.6.4, <= 2)
msgpack (1.6.0)
msgpack (1.5.4)
multi_json (1.15.0)
multi_xml (0.6.0)
net-protocol (0.1.3)
@@ -417,7 +418,7 @@ GEM
net-smtp (0.3.2)
net-protocol
nio4r (2.5.8)
nokogiri (1.13.10)
nokogiri (1.13.9)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
oauth2 (1.4.11)
@@ -451,9 +452,9 @@ GEM
activerecord (>= 5.2)
request_store (~> 1.1)
parallel (1.22.1)
paranoia (2.6.1)
paranoia (2.6.0)
activerecord (>= 5.1, < 7.1)
parser (3.1.3.0)
parser (3.1.2.1)
ast (~> 2.4.1)
paypal-sdk-core (0.3.4)
multi_json (~> 1.0)
@@ -475,7 +476,7 @@ GEM
puma (5.6.5)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.6.1)
racc (1.6.0)
rack (2.2.4)
rack-mini-profiler (2.3.4)
rack (>= 1.2.0)
@@ -524,7 +525,7 @@ GEM
ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.4.3)
loofah (~> 2.3)
rails-i18n (7.0.6)
rails-i18n (7.0.5)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
rails_safe_tasks (1.0.0)
@@ -545,7 +546,7 @@ GEM
ffi (~> 1.0)
redcarpet (3.5.1)
redis (4.8.0)
regexp_parser (2.6.1)
regexp_parser (2.6.0)
reline (0.3.1)
io-console (~> 0.5)
request_store (1.5.0)
@@ -589,17 +590,17 @@ GEM
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.10.3)
rswag-api (2.8.0)
rswag-api (2.7.0)
railties (>= 3.1, < 7.1)
rswag-specs (2.8.0)
rswag-specs (2.7.0)
activesupport (>= 3.1, < 7.1)
json-schema (>= 2.2, < 4.0)
railties (>= 3.1, < 7.1)
rspec-core (>= 2.14)
rswag-ui (2.8.0)
rswag-ui (2.7.0)
actionpack (>= 3.1, < 7.1)
railties (>= 3.1, < 7.1)
rubocop (1.40.0)
rubocop (1.38.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.1.2.1)
@@ -609,9 +610,9 @@ GEM
rubocop-ast (>= 1.23.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.24.0)
rubocop-ast (1.23.0)
parser (>= 3.1.1.0)
rubocop-rails (2.17.3)
rubocop-rails (2.17.2)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
@@ -682,18 +683,19 @@ GEM
railties (>= 5.2)
redis
stringex (2.8.5)
stripe (8.0.0)
stripe (7.1.0)
swd (1.3.0)
activesupport (>= 3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
temple (0.8.2)
test-prof (1.0.11)
test-unit (3.5.5)
power_assert
thor (1.2.1)
thread-local (1.1.0)
tilt (2.0.11)
timecop (0.9.6)
timecop (0.9.5)
timeout (0.3.0)
ttfunk (1.7.0)
tzinfo (2.0.5)
@@ -710,7 +712,7 @@ GEM
activemodel (>= 3.0.0)
public_suffix
vcr (6.1.0)
view_component (2.78.0)
view_component (2.75.0)
activesupport (>= 5.0.0, < 8.0)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
@@ -735,7 +737,6 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.7.0)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -743,11 +744,11 @@ GEM
chronic (>= 0.6.3)
wicked_pdf (2.6.3)
activesupport
wkhtmltopdf-binary (0.12.6.6)
wkhtmltopdf-binary (0.12.6.5)
xml-simple (1.1.8)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.6)
zeitwerk (2.6.4)
PLATFORMS
ruby
@@ -817,12 +818,11 @@ DEPENDENCIES
json_spec (~> 1.1.4)
jsonapi-serializer
jwt (~> 2.3)
knapsack_pro
knapsack
letter_opener (>= 1.4.1)
listen
mime-types
mimemagic (> 0.3.5)
mini_portile2 (~> 2.8)
mini_racer (= 0.4.0)
monetize (~> 1.11)
oauth2 (~> 1.4.7)
@@ -874,6 +874,7 @@ DEPENDENCIES
stimulus_reflex (= 3.5.0.pre9)
stringex (~> 2.8.5)
stripe
test-prof
test-unit (~> 3.5)
timecop
valid_email2

View File

@@ -8,3 +8,6 @@ require_relative 'config/application'
Openfoodnetwork::Application.load_tasks
if !ENV['DISABLE_KNAPSACK'] && defined?(Knapsack)
Knapsack.load_tasks
end

View File

@@ -1,7 +1,5 @@
# frozen_string_literal: true
require "open_food_network/feature_toggle"
class FeatureToggleConstraint
def initialize(feature_name)
@feature = feature_name
@@ -12,6 +10,6 @@ class FeatureToggleConstraint
end
def current_user(request)
request.env['warden']&.user
request.env['warden'].user
end
end

View File

@@ -116,7 +116,21 @@ module Admin
# Fetches tags for all customers of the enterprise and returns a hash indexed by customer_id
def customer_tags_by_id
BatchTaggableTagsQuery.call(Customer.of(managed_enterprise_id))
customer_tags = ::ActsAsTaggableOn::Tag.
joins(:taggings).
includes(:taggings).
where(taggings:
{ taggable_type: 'Customer',
taggable_id: Customer.of(managed_enterprise_id),
context: 'tags' })
customer_tags.each_with_object({}) do |tag, indexed_hash|
tag.taggings.each do |tagging|
customer_id = tagging.taggable_id
indexed_hash[customer_id] ||= []
indexed_hash[customer_id] << tag.name
end
end
end
end
end

View File

@@ -162,20 +162,25 @@ module Admin
[:index]
end
def managed_enterprise_id
Enterprise.managed_by(spree_current_user).select('enterprises.id').
find_by(id: params[:enterprise_id])
end
def subscription_params
@subscription_params ||= PermittedAttributes::Subscription.new(params).call.
to_h.with_indifferent_access
end
def payment_method_tags_by_id
@payment_method_tags_by_id ||= BatchTaggableTagsQuery.call(
Spree::PaymentMethod.from(managed_enterprise_id)
)
payment_method_tags = ::ActsAsTaggableOn::Tag.
joins(:taggings).
includes(:taggings).
where(taggings: { taggable_type: "Spree::PaymentMethod",
taggable_id: Spree::PaymentMethod.from(Enterprise.managed_by(spree_current_user).
select('enterprises.id').find_by(id: params[:enterprise_id])),
context: 'tags' })
payment_method_tags.each_with_object({}) do |tag, hash|
payment_method_id = tag.taggings.first.taggable_id
hash[payment_method_id] ||= []
hash[payment_method_id] << tag.name
end
end
end
end

View File

@@ -68,31 +68,21 @@ module ReportsActions
user: spree_current_user,
report_type: report_type,
report_subtype: report_subtype
).first_or_create do |report_rendering_options|
report_rendering_options.options = {
fields_to_show: if request.get?
@report.columns.keys -
@report.fields_to_hide
else
params[:fields_to_show]
end,
display_summary_row: request.get?,
display_header_row: false
}
).first_or_create do |new_instance|
new_instance.options[:fields_to_show] = if @report.present?
@report.columns.keys - @report.fields_to_hide
else
[]
end
new_instance.options[:display_summary_row] = request.get? || params[:display_summary_row].present?
params[:display_header_row] = params[:display_header_row].present?
end
update_rendering_options
if params[:fields_to_show].present?
@rendering_options.options[:fields_to_show] = params[:fields_to_show]
end
@rendering_options.options[:display_summary_row] = params[:display_summary_row].present?
@rendering_options.options[:display_header_row] = params[:display_header_row].present?
@rendering_options.save
@rendering_options
end
def update_rendering_options
return unless request.post?
@rendering_options.update(
options: {
fields_to_show: params[:fields_to_show],
display_summary_row: params[:display_summary_row].present?,
display_header_row: params[:display_header_row].present?
}
)
end
end

View File

@@ -34,7 +34,6 @@ module Spree
link = link_to_with_icon(options[:icon], titleized_label, destination_url)
css_classes << 'tab-with-icon'
else
titleized_label = raw("<span class='text'>#{titleized_label}</span>")
link = link_to(titleized_label, destination_url)
end

View File

@@ -6,9 +6,9 @@ class Enterprise < ApplicationRecord
# The next Rails version will have named variants but we need to store them
# ourselves for now.
LOGO_SIZES = {
thumb: { gravity: "Center", resize: "100x100^", crop: '100x100+0+0' },
small: { gravity: "Center", resize: "180x180^", crop: '180x180+0+0' },
medium: { gravity: "Center", resize: "300x300^", crop: '300x300+0+0' },
thumb: { resize_to_limit: [100, 100] },
small: { resize_to_limit: [180, 180] },
medium: { resize_to_limit: [300, 300] },
}.freeze
PROMO_IMAGE_SIZES = {
thumb: { resize_to_limit: [100, 100] },

View File

@@ -1,5 +1,3 @@
# frozen_string_literal: true
class ReportRenderingOptions < ApplicationRecord
belongs_to :user, class_name: "Spree::User"
serialize :options, Hash

View File

@@ -37,7 +37,7 @@ module Spree
foreign_key: :owner_id, inverse_of: :owner
has_many :customers
has_many :credit_cards
has_many :report_rendering_options, class_name: "::ReportRenderingOptions", dependent: :destroy
accepts_nested_attributes_for :enterprise_roles, allow_destroy: true
accepts_nested_attributes_for :bill_address

View File

@@ -1,20 +0,0 @@
# frozen_string_literal: true
class BatchTaggableTagsQuery
def self.call(taggables)
::ActsAsTaggableOn::Tag.
joins(:taggings).
includes(:taggings).
where(taggings:
{
taggable_type: taggables.model.to_s,
taggable_id: taggables,
context: 'tags'
}).order("tags.name").each_with_object({}) do |tag, indexed_hash|
tag.taggings.each do |tagging|
indexed_hash[tagging.taggable_id] ||= []
indexed_hash[tagging.taggable_id] << tag.name
end
end
end
end

View File

@@ -42,18 +42,12 @@ module Api
.visible_variants_for_outgoing_exchanges_to(object.receiver)
end
def preloaded_tag_list
return object.tag_list unless options[:preloaded_tags]
options.dig(:preloaded_tags, object.id) || []
end
def tag_list
preloaded_tag_list.join(",")
object.tag_list.join(",")
end
def tags
preloaded_tag_list.map { |tag| { text: tag } }
object.tag_list.map{ |t| { text: t } }
end
end
end

View File

@@ -34,8 +34,7 @@ module Api
ActiveModel::ArraySerializer.
new(scoped_exchanges, each_serializer: Api::Admin::ExchangeSerializer,
current_user: options[:current_user],
preloaded_tags: BatchTaggableTagsQuery.call(scoped_exchanges))
current_user: options[:current_user])
end
def editable_variants_for_incoming_exchanges

View File

@@ -102,6 +102,7 @@
= af.label :latitude, t(:latitude)
\/
= af.label :longitude, t(:longitude)
%span.required *
%div{'ofn-with-tip' => t('latitude_longitude_tip')}
%a= t('admin.whats_this')
.four.columns

View File

@@ -41,6 +41,7 @@
= af.label :latitude, t(:latitude)
\/
= af.label :longitude, t(:longitude)
%span.required *
= render partial: 'admin/shared/tooltip', locals: {tooltip_text: t('latitude_longitude_tip')}
.four.columns
= af.text_field :latitude, { placeholder: t(:latitude_placeholder) }

View File

@@ -4,8 +4,7 @@
%br
100 x 100 pixels
.omega.eight.columns
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.logo.thumb }}', if: 'Enterprise.logo' } }
%br
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.logo.medium }}', if: 'Enterprise.logo' } }
= f.file_field :logo
%a.button.red{ href: '', ng: {click: 'removeLogo()', if: 'Enterprise.logo'} }
= t('.remove_logo')

View File

@@ -32,8 +32,6 @@
.four.columns.omega
= f.radio_button :sells, "any", 'ng-model' => 'Enterprise.sells', data: {action: "change->primary-details#enterpriseSellsChanged"}
= f.label :sells, t('.any'), value: "any"
%span{ style: "width: 30px; height: 30px;", class: "hidden", data: { "primary-details-target": "spinner" } }
= render partial: "components/admin_spinner"
.row
.three.columns.alpha
%label= t('.visible_in_search')

View File

@@ -4,7 +4,7 @@
.row.date-range-filter
.alpha.two.columns= label_tag nil, t(:date_range)
.omega.fourteen.columns
= f.text_field "#{field}_gt", :class => 'datetimepicker datepicker-from', :placeholder => t(:start), data: { controller: "flatpickr", "flatpickr-enable-time-value": true, "flatpickr-default-date-value": "startOfDay" }
= f.text_field "#{field}_gt", :class => 'datetimepicker datepicker-from', :placeholder => t(:start), data: { controller: "flatpickr", "flatpickr-enable-time-value": true }
%span.range-divider
%i.icon-arrow-right
= f.text_field "#{field}_lt", :class => 'datetimepicker datepicker-to', :placeholder => t(:stop), data: { controller: "flatpickr", "flatpickr-enable-time-value": true, "flatpickr-default-date-value": "endOfDay" }
= f.text_field "#{field}_lt", :class => 'datetimepicker datepicker-to', :placeholder => t(:stop), data: { controller: "flatpickr", "flatpickr-enable-time-value": true }

View File

@@ -16,16 +16,16 @@
.omega.fourteen.columns
- if @report.header_option?
%span.inline-checkbox{ style: "margin-right: 1rem;" }
= check_box_tag :display_header_row, true, @rendering_options.options[:display_header_row]
= check_box_tag :display_header_row, true, @render_options.options[:display_header_row]
= label_tag :display_header_row, t(".header_row")
- if @report.summary_row_option?
%span.inline-checkbox
= check_box_tag :display_summary_row, true, @rendering_options.options[:display_summary_row], { "data-csv-select-target": "checkbox" }
= check_box_tag :display_summary_row, true, @render_options.options[:display_summary_row], { "data-csv-select-target": "checkbox" }
= label_tag :display_summary_row, t(".summary_row"), { "data-csv-select-target": "label" }
- if @report.available_headers.present?
.row
.alpha.two.columns= label_tag nil, t(:report_columns)
.omega.fourteen.columns
= render MultipleCheckedSelectComponent.new(name: "fields_to_show", options: @report.available_headers, selected: @rendering_options.options[:fields_to_show])
= render MultipleCheckedSelectComponent.new(name: "fields_to_show", options: @report.available_headers, selected: @render_options.options[:fields_to_show])

View File

@@ -1,5 +1 @@
= render 'admin/reports/date_range_form', f: f
.row
.alpha.two.columns= label_tag nil, t(:report_hubs)
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.orders_distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true})

View File

@@ -2,7 +2,7 @@
%a{"ng-click" => "triggerProductModal()"}
%span.product-thumb__bulk-label{"ng-if" => "::product.group_buy"}
= t(".bulk")
%img{"ng-src" => "{{::product.primaryImageOrMissing}}"}
%img{"ng-src" => "{{::product.primaryImageOrMissing}}", loading: "lazy"}
.summary
.summary-header

View File

@@ -54,6 +54,6 @@
.actions.filter-actions
%a.button.icon-search{'ng-click' => 'fetchResults()'}
= t(:filter_results)
%a.button{'ng-click' => 'clearFilters()', "id": "clear_filters_button", "class": ("secondary" if feature?(:admin_style_v2, spree_current_user)) }
%a.button{'ng-click' => 'clearFilters()', "id": "clear_filters_button"}
= t(:clear_filters)

View File

@@ -95,17 +95,17 @@
%td.align-center
%span{'ng-bind-html' => 'order.display_total'}
%td.actions
.flex
%div.row-loading-icons
%div{ng: {show: 'rowStatus[order.id] == "loading"', cloak: true}, style: "width: 30px; height: 30px;"}
= render partial: "components/spinner"
%i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} }
%i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')}
%a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')}
%div{'ng-if' => 'order.ready_to_ship'}
%button.icon-road.icon_link.with-tip.no-text{'ng-click' => 'shipOrder(order)', rel: 'nofollow', 'ofn-with-tip' => t('.ship')}
%div{'ng-if' => 'order.ready_to_capture'}
%button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')}
%div.row-loading-icons
%div{ng: {show: 'rowStatus[order.id] == "loading"', cloak: true}, style: "width: 30px; height: 30px;"}
= render partial: "components/spinner"
%i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} }
%i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')}
%a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')}
%div{'ng-if' => 'order.ready_to_ship'}
%button.icon-road.icon_link.with-tip.no-text{'ng-click' => 'shipOrder(order)', rel: 'nofollow', 'ofn-with-tip' => t('.ship')}
%div{'ng-if' => 'order.ready_to_capture'}
%button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')}
.sixteen.columns.alpha#loading{ 'ng-show' => 'RequestMonitor.loading' }
= render partial: "components/admin_spinner"
%h1

View File

@@ -10,7 +10,7 @@
= t(controller.controller_name, :default => controller.controller_name.titleize)
= " - OFN #{t(:administration)}"
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600,700&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"}
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"}
= stylesheet_pack_tag 'admin-styles', media: "screen, print"
= render "layouts/bugsnag_js"

View File

@@ -3,7 +3,7 @@
%head{"data-hook" => "admin_inside_head"}
= render :partial => 'spree/admin/shared/head'
%body.admin{ "class": ("admin-v2" if feature?(:admin_style_v2, spree_current_user)) }
%body.admin
- if content_for?(:main_ng_app_name)
- if content_for?(:main_ng_ctrl_name)
%div{ "ng-app" => yield(:main_ng_app_name).strip.html_safe, "ng-controller" => yield(:main_ng_ctrl_name).strip.html_safe }

View File

@@ -1,31 +1,21 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["reportType", "checkbox", "label"];
static targets = ["reportType", "checkbox", "label"]
handleSelectChange() {
this.reportTypeTarget.value == "csv"
? this.disableField()
: this.enableField();
this.reportTypeTarget.value == "csv" ? this.disableField() : this.enableField()
}
disableField() {
if (this.hasCheckboxTarget) {
this.checkboxTarget.checked = false;
this.checkboxTarget.disabled = true;
}
if (this.hasLabelTarget) {
this.labelTarget.classList.add("disabled");
}
this.checkboxTarget.checked = false;
this.checkboxTarget.disabled = true;
this.labelTarget.classList.add("disabled");
}
enableField() {
if (this.hasCheckboxTarget) {
this.checkboxTarget.checked = true;
this.checkboxTarget.disabled = false;
}
if (this.hasLabelTarget) {
this.labelTarget.classList.remove("disabled");
}
this.checkboxTarget.checked = true;
this.checkboxTarget.disabled = false;
this.labelTarget.classList.remove("disabled");
}
}

View File

@@ -17,10 +17,7 @@ import ShortcutButtonsPlugin from "shortcut-buttons-flatpickr";
import labelPlugin from "flatpickr/dist/plugins/labelPlugin/labelPlugin";
export default class extends Flatpickr {
/*
* defaultDate (optional): "startOfDay" | "endOfDay"
*/
static values = { enableTime: Boolean, mode: String, defaultDate: String };
static values = { enableTime: Boolean, mode: String };
static targets = ["start", "end"];
locales = {
ar: ar,
@@ -63,9 +60,6 @@ export default class extends Flatpickr {
open() {
this.fp.element.dispatchEvent(new Event("focus"));
if (!this.fp.selectedDates.length) {
this.setDefaultDateValue();
}
}
onChangeEvent(e) {
if (
@@ -142,16 +136,4 @@ export default class extends Flatpickr {
break;
}
};
setDefaultDateValue() {
if (this.defaultDateValue === "startOfDay") {
this.fp.setDate(moment().startOf("day").format());
} else if (this.defaultDateValue === "endOfDay") {
/*
* We use "startOf('day')" of tomorrow in order to not lose
* the records between [23:59:00 ~ 23:59:59] of today
*/
this.fp.setDate(moment().add(1, "days").startOf("day").format());
}
}
}

View File

@@ -3,7 +3,6 @@ import CableReady from "cable_ready";
export default class extends Controller {
static values = { primaryProducer: String, enterpriseSells: String };
static targets = ["spinner"];
primaryProducerChanged(event) {
this.primaryProducerValue = event.currentTarget.checked;
@@ -13,7 +12,6 @@ export default class extends Controller {
enterpriseSellsChanged(event) {
if (event.currentTarget.checked) {
this.enterpriseSellsValue = event.currentTarget.value;
this.spinnerTarget.classList.remove("hidden");
this.makeRequest();
}
}
@@ -27,9 +25,6 @@ export default class extends Controller {
}
)
.then((data) => data.json())
.then((operation) => {
CableReady.perform(operation);
this.spinnerTarget.classList.add("hidden");
});
.then(CableReady.perform);
}
}

View File

@@ -120,5 +120,3 @@
@import "components/tom_select";
@import 'app/components/help_modal_component/help_modal_component';
@import "v2/main.scss";

View File

@@ -78,6 +78,7 @@ nav.menu {
text-transform: uppercase;
position: relative;
text-align: center;
font-weight: 600;
i {
display: inline;

View File

@@ -1,66 +0,0 @@
/* Overide buttons.scss app/webpacker/css/admin/components/buttons.scss */
@mixin backgroundAndBorder($color) {
background-color: $color;
border: 2px solid $color;
}
input[type="submit"],
select[type="submit"],
.select2-container-multi [type="submit"].select2-choices,
input[type="button"],
select[type="button"],
.select2-container-multi [type="button"].select2-choices,
button,
.button,
.actions a:not([class*="icon-"]),
.admin__section-header .ofn-drop-down // Same behavior as the button
{
&.disabled,
&[disabled] {
@include backgroundAndBorder($v2-light-grey);
}
&:not(.disabled):not([disabled]):not(.secondary) {
// Change the color of the button only if it's not disabled
@include backgroundAndBorder($v2-blue-light);
&:hover {
@include backgroundAndBorder($v2-blue);
box-shadow: $v2-box-shadow;
}
}
&.secondary {
background-color: $white;
border: 2px solid $v2-blue-light;
color: $v2-blue-light;
&:hover {
background-color: $v2-blue-lightest;
color: $v2-blue;
box-shadow: $v2-box-shadow;
}
}
&.active {
@include backgroundAndBorder($v2-blue);
}
}
#table-filter .actions {
/* used to draw a line on the right and left of the actions buttons
We can then remove the dropshadow on the buttons */
&:before,
&:after {
background-color: $v2-light-grey; // same color as the border of the fieldset. see forms.scss
height: 1px;
content: attr(data-initials);
flex-grow: 1; // make the line as long as it can
}
}
#table-filter fieldset:has(.actions) {
// do not apply border to filter actions as it's drawn by the #table-filter .actions before and after pseudo elements
border-bottom: 0;
}

View File

@@ -1,9 +0,0 @@
/* Overide app/webpacker/css/admin/components/progress.scss file */
#progress {
background-color: $v2-blue;
}
#loading {
color: $v2-blue;
}

View File

@@ -1,73 +0,0 @@
/* Overide tables.scss app/webpacker/css/admin/components/tables.scss */
table thead th {
background-color: $v2-medium-light-grey;
border: none;
color: $v2-blue;
text-transform: capitalize;
font-size: 13px;
a {
border: none;
color: $v2-blue;
}
}
table tbody tr {
&:first-child th,
&:first-child td {
border-top: none; // Don't show the top border of the first row
}
td:not(:first-child) {
border-left: none; // Only show left border on the first cells, as it indicates the order state by its color
}
td {
border-bottom: none; // By default, do not show the border of the cells
border-right: none;
border-top: none;
border-bottom: 2px solid $v2-medium-light-grey;
&.actions {
border-bottom: 2px solid $v2-medium-light-grey !important; // needs to be important because of already defined with important
}
> .flex {
display: flex;
column-gap: 10px;
}
}
&.even,
&.odd {
td {
background-color: transparent; // Do not use odd and even colors for background
}
}
}
table th.actions,
table td.actions {
// Special for icons in the actions column
[class*="icon-"].no-text {
border: 2px solid $v2-blue-light;
background-color: $v2-blue-lightest;
&:hover {
border-color: $v2-blue;
background-color: $v2-blue-light;
box-shadow: $v2-box-shadow;
&:before {
color: white;
}
}
}
}
table#listing_orders td {
// When the table is the listing of orders, we need to increase the height of the cells
padding: 20px 0;
&.actions {
padding-left: 20px;
}
}

View File

@@ -1,13 +0,0 @@
@import "variables.scss";
@import "shared/typography.scss";
body.admin.admin-v2 {
@import "navigation.scss";
@import "plugins/select2.scss";
@import "plugins/powertip.scss";
@import "plugins/flatpickr-customization.scss";
@import "shared/forms.scss";
@import "components/buttons.scss";
@import "components/tables.scss";
@import "components/progress.scss";
}

View File

@@ -1,62 +0,0 @@
#header {
#login-nav {
li {
color: $v2-medium-dark-grey;
i {
@include v2-link-color();
}
}
}
}
#admin-menu {
background-color: $v2-orange;
li a span.text {
font-weight: 700;
}
li.tab-with-icon a:before {
display: none;
}
li a:hover,
li.selected a {
background-color: $v2-orange-light;
span {
text-shadow: 1px 1px 9px $v2-orange;
}
&:after {
display: none;
}
}
}
#sub-menu {
background-color: $v2-orange-light;
li a {
font-size: 100%;
}
li a:hover,
li.selected a {
text-shadow: 1px 1px 9px $v2-orange;
background-color: lighten($v2-orange-light, 7%);
&:after {
display: none;
}
}
}
.admin__section-header {
background-color: transparent;
border-bottom: none;
h1.js-admin-page-title {
color: $v2-medium-dark-grey;
}
}

View File

@@ -1,46 +0,0 @@
/* Override flatpickr styles: app/webpacker/css/admin/plugins/flatpickr-customization.scss */
.flatpickr-calendar {
&.arrowTop::after {
border-bottom-color: $v2-blue-light;
}
.flatpickr-months .flatpickr-month,
.flatpickr-current-month .flatpickr-monthDropdown-months {
background: $v2-blue-light;
color: white;
input {
color: white;
}
}
.flatpickr-weekdays {
background: $v2-blue-light;
.flatpickr-weekday {
background: $v2-blue-light;
color: white;
}
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
background: $v2-blue-light;
border-color: $v2-blue-light;
}
}

View File

@@ -1,31 +0,0 @@
/* Overide file powertip.scss app/webpacker/css/admin/v2/plugins/powertip.scss */
#powerTip {
background-color: $v2-blue;
&.n:before,
&.ne:before,
&.nw:before {
border-top-color: $v2-blue;
}
&.e:before {
border-right-color: $v2-blue;
}
&.s:before,
&.se:before,
&.sw:before {
border-bottom-color: $v2-blue;
}
&.w:before {
border-left-color: $v2-blue;
}
&.ne:before,
&.se:before {
border-right-color: $v2-blue;
}
&.nw:before,
&.sw:before {
border-right-color: $v2-blue;
}
}

View File

@@ -1,70 +0,0 @@
/* Override select2 styles app/webpacker/css/admin/plugins/select2.scss */
.select2-container {
.select2-choice {
background-color: transparent;
border: 1px solid $v2-light-grey !important;
color: $v2-medium-grey !important;
padding-left: 5px;
font-size: 13px;
padding-top: 3px;
.select2-arrow {
color: $v2-medium-grey;
}
}
&.select2-container-active,
&:hover {
.select2-choice {
background-color: transparent !important;
border-color: $v2-medium-grey !important;
}
}
&.select2-dropdown-open.select2-container-active {
&:not(.select2-drop-above) {
.select2-choice {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
&.select2-drop-above .select.select2-choice {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
.select2-container-multi {
.select2-choices {
border-color: $v2-medium-grey !important;
.select2-search-choice {
background-color: $v2-blue-light;
}
}
}
.select2-drop {
border-color: $v2-medium-grey;
}
.select2-search {
color: $v2-medium-grey;
}
.select2-results {
margin-right: 0;
li {
.select2-result-label {
color: $v2-medium-grey;
}
&.select2-highlighted {
background-color: $v2-blue;
}
&.select2-no-results,
&.select2-searching {
color: $v2-medium-grey;
}
}
}

View File

@@ -1,55 +0,0 @@
/* Overide forms.scss app/webpacker/css/admin/shared/forms.scss */
input[type="text"],
.select2-container-multi .select2-choices,
.select2-search input,
.select2-search select,
select,
input[type="password"],
input[type="email"],
input[type="url"],
input[type="tel"],
input[type="date"],
input[type="datetime"],
input[type="time"],
input[type="number"],
textarea,
fieldset {
// Change the color of all inputs
color: $v2-medium-grey;
border-color: $v2-light-grey !important;
&:focus {
border-color: $v2-medium-grey;
}
}
fieldset label {
color: $v2-medium-grey;
}
fieldset legend {
color: $v2-blue;
}
input[type="checkbox"],
input[type="radio"] {
accent-color: $v2-blue;
}
fieldset .filter-actions {
button,
.button,
input[type="submit"] {
box-shadow: none;
width: 200px; // adjust at the same size in order to center them. Not ideal but works for now.
&:first-of-type {
margin-right: 0; // don't see any reason to have a margin right on the first button as it's managed by the flexbox
}
&:hover {
box-shadow: $v2-box-shadow;
}
}
}

View File

@@ -1,18 +0,0 @@
// Overide app/webpacker/css/admin/shared/typography.scss
@mixin v2-link-color() {
color: $v2-blue;
border-color: $v2-blue;
&:hover {
color: $v2-blue-dark;
border-color: $v2-blue-dark;
}
}
body.admin.admin-v2 {
color: $v2-body-grey;
a:not(.button) {
@include v2-link-color();
}
}

View File

@@ -1,23 +0,0 @@
// Should finally replace (or at least complete) the file /admin/globale/variables.scss
$v2-orange: #f27052;
$v2-orange-light: #f5947d;
$v2-orange-lighter: #f8b7a8;
$v2-orange-lightest: #fcdbd4;
$v2-dark-grey: #333333;
$v2-medium-dark-grey: #444444;
$v2-body-grey: #666666;
$v2-medium-grey: #717171;
$v2-medium-light-grey: #e6e6e6;
$v2-light-grey: #e7e7e7;
$v2-blue: #017a9a;
$v2-blue-dark: #005e7a;
$v2-blue-light: #0096ad;
$v2-blue-lightest: #e6f7fa; // Could be used as a background color for the action icons
$v2-green: #019854;
$v2-green-light: #01cb70;
$v2-box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); // Default box shadow for actions stuff

View File

@@ -1,13 +0,0 @@
#!/bin/bash
if [ "$KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC" = "" ]; then
KNAPSACK_PRO_ENDPOINT=https://api-disabled-for-fork.knapsackpro.com \
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC=disabled-for-fork \
KNAPSACK_PRO_MAX_REQUEST_RETRIES=0 \
bundle exec rake knapsack_pro:rspec # use Regular Mode here always
else
# Regular Mode
bundle exec rake knapsack_pro:rspec
# or you can use Queue Mode instead of Regular Mode if you like
# bundle exec rake knapsack_pro:queue:rspec
fi

View File

@@ -155,17 +155,15 @@ module Openfoodnetwork
initializer "ofn.reports" do |app|
module ::Reporting; end
Rails.application.reloader.to_prepare do
loader = Zeitwerk::Loader.new
loader.push_dir("#{Rails.root}/lib/reporting", namespace: ::Reporting)
loader.enable_reloading
loader.setup
loader.eager_load
loader = Zeitwerk::Loader.new
loader.push_dir("#{Rails.root}/lib/reporting", namespace: ::Reporting)
loader.enable_reloading
loader.setup
loader.eager_load
if Rails.env.development?
require 'listen'
Listen.to("lib/reporting") { loader.reload }.start
end
if Rails.env.development?
require 'listen'
Listen.to("lib/reporting") { loader.reload }.start
end
end
@@ -249,7 +247,5 @@ module Openfoodnetwork
config.active_storage.variable_content_types += ["image/svg+xml"]
config.exceptions_app = self.routes
config.autoloader = :zeitwerk
end
end

View File

@@ -627,7 +627,6 @@ de_DE:
conditional_blank: Darf nicht leer sein, wenn das Feld 'unit_type' leer ist.
no_product: Es konnten keine passenden Produkte in der Datenbank gefunden werden.
not_found: Konnte nicht in der Datenbank gefunden werden.
category_not_found: stimmt nicht mit den verfügbaren Kategorien überein. Diese finden Sie auf der Seite zum Produktimport. Überprüfen Sie zusätzlich Ihre Angaben auf Tippfehler.
not_updatable: Kann über den Produktimport nicht auf bestehende Produkte aktualisiert werden.
blank: darf nicht leer sein
products_no_permission: Sie sind nicht berechtigt, Produkte dieses Unternehmens zu verwalten.

View File

@@ -30,7 +30,6 @@ en_CA:
shipping_category_id: "Shipping Category"
variant_unit: "Variant Unit"
variant_unit_name: "Variant Unit Name"
unit_value: "Unit value"
spree/credit_card:
base: "Credit Card"
number: "Number"
@@ -627,7 +626,6 @@ en_CA:
conditional_blank: can't be blank if unit_type is blank
no_product: did not match any products in the database
not_found: not found in database
category_not_found: doesn't match allowed categories. See the correct categories to choose from on the product import page, or check that there's no misspelling.
not_updatable: cannot be updated on existing products via product import
blank: can't be blank
products_no_permission: you do not have permission to manage products for this enterprise
@@ -884,7 +882,7 @@ en_CA:
name: Name
name_placeholder: eg. Professor Plum's Biodynamic Truffles
groups: Groups
groups_tip: Select any markets, networks or groups that you are a member of. This will help customers find your enterprise.
groups_tip: Select any markets or groups that you are a member of. This will help customers find your enterprise.
groups_placeholder: Start typing to search available markets or groups...
primary_producer: Primary Producer?
primary_producer_tip: Select 'Producer' if you are a primary producer, grower, maker or designer
@@ -1581,7 +1579,7 @@ en_CA:
menu_2_url: "/map"
menu_3_title: "Producers"
menu_3_url: "/producers"
menu_4_title: "Networks"
menu_4_title: "Markets"
menu_4_url: "/groups"
menu_5_title: "About"
menu_5_url: "https://about.openfoodnetwork.ca"
@@ -1643,7 +1641,7 @@ en_CA:
label_map: "Map"
label_producer: "Producer"
label_producers: "Producers"
label_groups: "Networks"
label_groups: "Markets"
label_about: "About"
label_blog: "Blog"
label_support: "Support"
@@ -1982,7 +1980,7 @@ en_CA:
shopping_tabs_about: "About"
shopping_tabs_producers: "Producers"
shopping_tabs_contact: "Contact"
shopping_tabs_groups: "Networks"
shopping_tabs_groups: "Markets"
shopping_contact_address: "Address"
shopping_contact_web: "Contact"
shopping_contact_social: "Follow"
@@ -2047,14 +2045,14 @@ en_CA:
components_profiles_show: "Show profiles"
components_filters_nofilters: "No filters"
components_filters_clearfilters: "Clear all filters"
groups_title: Networks
groups_headline: 'Networks / Regions '
groups_text: "Networks are collectives of producers, hubs and distributors who share something in common like location, farmers market or philosophy. This makes your shopping experience easier. So explore our networks and have the curating done for you."
groups_title: Markets
groups_headline: 'Markets / Regions '
groups_text: "Markets are collectives of producers, hubs and distributors who share something in common like location, farmers market or philosophy. This makes your shopping experience easier. So explore our groups and have the curating done for you."
groups_search: "Search name or keyword"
groups_no_groups: "No groups found"
groups_about: "About Us"
groups_producers: "Members"
groups_hubs: "Go Shopping"
groups_producers: "Our vendors"
groups_hubs: "Go Shopping!"
groups_contact_web: Contact
groups_contact_social: Follow
groups_contact_address: Address

View File

@@ -627,7 +627,6 @@ en_FR:
conditional_blank: can't be blank if unit_type is blank
no_product: did not match any products in the database
not_found: not found in database
category_not_found: doesn't match allowed categories. See the correct categories to choose from on the product import page, or check that there's no misspelling.
not_updatable: cannot be updated on existing products via product import
blank: can't be blank
products_no_permission: you do not have permission to manage products for this enterprise

View File

@@ -1530,9 +1530,9 @@ en_US:
menu_4_url: "/groups"
menu_5_title: "About"
menu_5_url: "https://about.openfoodnetwork.net/"
menu_6_title: "Pricing"
menu_6_url: "https://about.openfoodnetwork.net/?page_id=114"
menu_7_title: "Help"
menu_6_title: "Donate"
menu_6_url: "https://donate.openfoodnetwork.net"
menu_7_title: "Support"
menu_7_url: "https://about.openfoodnetwork.net/?page_id=1123"
logo: "Logo (640x130)"
logo_mobile: "Mobile logo (75x26)"

View File

@@ -1,5 +1,5 @@
es:
language_name: "Español"
language_name: "Inglés"
activerecord:
models:
spree/product: Producto

View File

@@ -627,7 +627,6 @@ fr:
conditional_blank: ne peut pas être vide si unit_type est vide
no_product: n'a pu être associé à aucun produit existant dans la base de données
not_found: non trouvé dans le base de données
category_not_found: n'est pas conforme aux catégories utilisées. Merci de modifier les catégories en utilisant celles listées sur la page d'import ou vérifier qu'il n'y ait pas de faute de frappe ou d'espace à fin du mot.
not_updatable: ne peut pas être mis à jour pour des produits existants via la fonctionnalité d'import de fichier produits
blank: Champ obligatoire
products_no_permission: vous n'avez pas l'autorisation de gérer les produits de cette entreprise
@@ -1344,7 +1343,7 @@ fr:
spreadsheet: "Tableur (Excel, LibreOffice,...)"
display: Afficher
summary_row: Ligne total produits commandés
header_row: Ligne d'en-tête
header_row: Ligne d'en-tête (nom client·e)
raw_data: Données brutes
formatted_data: Données formatées
packing:
@@ -1806,7 +1805,7 @@ fr:
label: Ville
placeholder: ex. Metz
state_id:
label: Département
label: Statut
zipcode:
label: Code postal
placeholder: ex. 57000
@@ -2430,7 +2429,7 @@ fr:
admin_enterprise_groups_web_website_placeholder: "ex: www.maferme.fr"
admin_order_cycles: "Gérer les cycles de vente"
open: "Ouvre"
close: "Ferme"
close: "Annuler"
create: "Créer"
search: "Rechercher"
supplier: "Fournisseur"
@@ -2862,7 +2861,7 @@ fr:
deleting_item_will_cancel_order: "Cette opération va rendre une ou plusieurs commandes vides, sans aucun produit. Elles vont ainsi être annulées. Souhaitez-vous continuer ?"
modals:
got_it: "J'ai compris"
close: "Valider"
close: "Fermer"
continue: "Suivant"
invite: "Inviter"
invite_title: "Inviter un nouvel utilisateur"
@@ -3027,7 +3026,7 @@ fr:
inventory_tagged_bottom: "sont:"
new_tag_rule_dialog:
select_rule_type: "Choisir le type de règle:"
add_rule: "Valider"
add_rule: "Ajouter une règle"
enterprise_fees:
inherit_from_product: "Hériter du produit"
orders:
@@ -4111,7 +4110,7 @@ fr:
thanks: "Merci pour votre commande."
track_information: "Informations de suivi : %{tracking}"
track_link: "Lien de suivi : %{url}"
picked_up_instructions: "Votre commande auprès de %{distributor} vous a bien été délivrée :)"
picked_up_instructions: "Votre commande de %{distributor} a bien été réceptionnée"
picked_up_subject: "Notification de réception"
test_mailer:
test_email:

View File

@@ -30,7 +30,6 @@ fr_CA:
shipping_category_id: "Condition de transport"
variant_unit: "Unité"
variant_unit_name: "Unité de la variante"
unit_value: "Nb unités"
spree/credit_card:
base: "Carte de crédit"
number: "N° commande"
@@ -628,7 +627,6 @@ fr_CA:
conditional_blank: Champ obligatoire si le type d'unité est vide
no_product: 'aucun produit trouvé '
not_found: n'a pas été trouvé dans la base de donnée
category_not_found: n'est pas conforme aux catégories utilisées. Merci de modifier les catégories en utilisant celles listées sur la page d'import ou vérifier qu'il n'y ait pas de faute de frappe ou d'espace à fin du mot.
not_updatable: ne peut pas être mis à jour pour des produits existants via la fonctionnalité d'import de fichier produits
blank: Champ obligatoire
products_no_permission: vous n'avez pas les droits requis pour gérer les produits de cette entreprise

View File

@@ -628,7 +628,6 @@ ru:
conditional_blank: не может быть пустым, если unit_type пуст
no_product: не найдено ни одного товара в базе данных
not_found: не найден в базе данных
category_not_found: не соответствует разрешенным категориям. Посмотрите, какие категории выбрать на странице импорта продуктов, или проверьте, нет ли орфографических ошибок.
not_updatable: невозможно обновить существующие товары с помощью импорта товаров
blank: не может быть пустым
products_no_permission: у Вас нет разрешения на управление товарами этого предприятия
@@ -1991,7 +1990,7 @@ ru:
shopping_contact_social: "Следовать"
shopping_groups_part_of: "часть:"
shopping_producers_of_hub: "%{hub} производители:"
enterprises_next_closing: "Закрытие заказа"
enterprises_next_closing: "Закрытие заказа через"
enterprises_currently_open: "Заказы открыты"
enterprises_ready_for: "Готов к"
enterprises_choose: "Выберите, когда вы хотите свой заказ:"
@@ -3116,7 +3115,7 @@ ru:
min_quantity: "Мин. количество"
max_quantity: "Макс количество"
price_breakdown: "Разбивка цен"
unit_price_tooltip: "Цена за единицу этого продукта. Это позволяет сравнивать цены на товары независимо от размера и веса упаковки."
unit_price_tooltip: "Это цена за единицу этого продукта. Это позволяет сравнивать цены на товары независимо от размера и веса упаковки."
variants:
on_demand:
'yes': "По Запросу"

View File

@@ -117,7 +117,7 @@ Openfoodnetwork::Application.routes.draw do
get 'sitemap.xml', to: 'sitemap#index', defaults: { format: 'xml' }
constraints FeatureToggleConstraint.new(:dfc_provider) do
unless Rails.env.production?
# Mount DFC API endpoints
mount DfcProvider::Engine, at: '/'
end

View File

@@ -13,6 +13,7 @@
ActiveRecord::Schema.define(version: 2022_11_16_095826) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
create_table "active_storage_attachments", force: :cascade do |t|

View File

@@ -5,9 +5,7 @@ module Reporting
module BulkCoop
class PackingSheets < Base
def query_result
table_items.group_by do |item|
[item.order.customer, item.variant]
end.values
table_items.group_by(&:order).values
end
def columns

View File

@@ -43,10 +43,6 @@ module Reporting
proc { |line_items| line_items.first.variant.full_name }
end
def variant_sku
proc { |line_items| line_items.first.variant.sku }
end
def supplier_name
proc { |line_items| line_items.first.variant.product.supplier.name }
end

View File

@@ -12,8 +12,7 @@ module Reporting
quantity: proc { |line_items| line_items.sum(&:quantity) },
total_units: proc { |line_items| total_units(line_items) },
curr_cost_per_unit: proc { |line_items| line_items.first.price },
total_cost: proc { |line_items| line_items.sum(&:amount) },
sku: variant_sku
total_cost: proc { |line_items| line_items.sum(&:amount) }
}
end
@@ -42,10 +41,6 @@ module Reporting
[e.variant_id, e.price]
}.values
end
def default_params
super.merge({ fields_to_hide: ["sku"] })
end
end
end
end

78
lib/tasks/specs.rake Normal file
View File

@@ -0,0 +1,78 @@
# frozen_string_literal: true
namespace :ofn do
namespace :specs do
namespace :run do
def spec_folders
Pathname("spec/").children.select(&:directory?).map { |p|
p.split.last.to_s
} - %w(support factories javascripts performance)
end
def execute_rspec_for_pattern(pattern)
system "bundle exec rspec --profile --pattern \"#{pattern}\""
end
def execute_rspec_for_spec_folder(folder)
execute_rspec_for_pattern("spec/#{folder}/{,/*/**}/*_spec.rb")
end
def execute_rspec_for_spec_folders(folders)
folders = folders.join(",")
execute_rspec_for_pattern("spec/{#{folders}}/{,/*/**}/*_spec.rb")
end
desc "Run Rspec tests excluding folders"
task :excluding_folders, [:folders] => :environment do |_task, args|
success = execute_rspec_for_spec_folders(
spec_folders - (args[:folders].split(",") + args.extras)
)
abort "Failure when running tests" unless success
end
end
namespace :engines do
def detect_engine_paths
Pathname("engines/").children.select(&:directory?)
end
def engine_name_for_engine(engine_path)
engine_path.basename.to_path
end
def execute_rspec_for_engine(engine_path)
system "DISABLE_KNAPSACK=true bundle exec rspec #{engine_path.expand_path}/spec"
end
engine_paths = detect_engine_paths
engine_paths.each do |engine_path|
engine_name = engine_name_for_engine(engine_path)
namespace engine_name do
desc "Run RSpec tests for engine \"#{engine_name}\""
task rspec: :environment do
success = execute_rspec_for_engine(engine_path)
abort "Failure when running tests for engine \"#{engine_name}\"" unless success
end
end
end
namespace :all do
desc "Run RSpec tests for all engines"
task rspec: :environment do
success = true
engine_paths.each do |engine_path|
success = !!execute_rspec_for_engine(engine_path) && success
end
abort "Failure encountered when running tests for engines" unless success
end
end
desc "Alias for openfoodnetwork:specs:engines:all:rspec"
task rspec: "all:rspec"
end
end
end

View File

@@ -24,15 +24,12 @@ Shoulda::Matchers.configure do |config|
end
end
require 'knapsack_pro'
KnapsackPro::Adapters::RSpecAdapter.bind
# Allow connections to selenium whilst raising errors when connecting to external sites
require 'webmock/rspec'
WebMock.enable!
WebMock.disable_net_connect!(
allow_localhost: true,
allow: ['chromedriver.storage.googleapis.com', 'api.knapsackpro.com']
allow: 'chromedriver.storage.googleapis.com'
)
# Requires supporting ruby files with custom matchers and macros, etc,
@@ -132,6 +129,7 @@ RSpec.configure do |config|
config.include Spree::UrlHelpers
config.include Spree::MoneyHelper
config.include PreferencesHelper
config.include OpenFoodNetwork::FeatureToggleHelper
config.include OpenFoodNetwork::FiltersHelper
config.include OpenFoodNetwork::EnterpriseGroupsHelper
config.include OpenFoodNetwork::ProductsHelper

View File

@@ -116,43 +116,6 @@ module Admin
end
end
end
describe "queries" do
context "as manager, when order cycle has multiple exchanges" do
let!(:distributor) { create(:distributor_enterprise) }
let(:order_cycle) { create(:simple_order_cycle, coordinator: distributor) }
before do
order_cycle.exchanges.create! sender: distributor, receiver: distributor, incoming: true,
receival_instructions: 'A', tag_list: "A"
order_cycle.exchanges.create! sender: distributor, receiver: distributor, incoming: false,
pickup_instructions: 'B', tag_list: "B"
controller_login_as_enterprise_user([distributor])
end
it do
query_counter = QueryCounter.new
get :show, params: { id: order_cycle.id }, as: :json
expect(query_counter.queries).to eq(
{
select: {
enterprise_fees: 3,
enterprise_groups: 1,
enterprises: 22,
exchanges: 7,
order_cycles: 6,
proxy_orders: 1,
schedules: 1,
spree_roles: 9,
spree_variants: 8,
tags: 1
},
update: { spree_users: 1 }
}
)
query_counter.stop
end
end
end
end
describe "create" do

View File

@@ -88,7 +88,10 @@ module PaymentGateways
context "using split checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout) { true }
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything) { true }
order.update_attribute :state, "confirmation"
end

View File

@@ -16,7 +16,10 @@ describe SplitCheckoutController, type: :controller do
let(:shipping_method) { distributor.shipping_methods.first }
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout) { true }
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything) { true }
exchange.variants << order.line_items.first.variant
allow(controller).to receive(:current_order) { order }

View File

@@ -25,7 +25,6 @@ module Reporting
context 'with completed order' do
let(:bill_address) { create(:address) }
let(:distributor) { create(:distributor_enterprise) }
let(:distributor1) { create(:distributor_enterprise) }
let(:product) { create(:product) }
let(:shipping_method) { create(:shipping_method) }
let(:shipping_instructions) { 'pick up on thursday please!' }
@@ -83,26 +82,6 @@ module Reporting
table = subject.table_rows
expect(table.size).to eq 2
end
context "filtering by distributor" do
it do
create(:line_item_with_shipment, order: order)
report1 = Base.new(create(:admin_user), {})
table = report1.table_rows
expect(table.size).to eq 2
report2 = Base.new(create(:admin_user),
{ q: { distributor_id_in: [distributor.id] } })
table2 = report2.table_rows
expect(table2.size).to eq 2
report3 = Base.new(create(:admin_user),
{ q: { distributor_id_in: [distributor1.id] } })
table3 = report3.table_rows
expect(table3.size).to eq 0
end
end
end
end
end

View File

@@ -18,10 +18,6 @@ module Reporting
OrderCycleSupplierTotals.new(current_user, params)
end
let(:table_headers) do
report.table_headers
end
let(:report_table) do
report.table_rows
end
@@ -35,15 +31,6 @@ module Reporting
supplier_name_field = report_table.first[0]
expect(supplier_name_field).to eq supplier.name
end
it "includes sku column" do
variant_sku = order.line_items.first.variant.sku
last_column_title = table_headers.last
first_row_last_column_value = report_table.first.last
expect(last_column_title).to eq "SKU"
expect(first_row_last_column_value).to eq variant_sku
end
end
end
end

View File

@@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ReportRenderingOptions, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@@ -88,8 +88,8 @@ describe Spree::Payment do
before do
allow(payment).to receive(:record_response)
allow(card).to receive(:has_payment_profile?).and_return(true)
allow(payment).to receive(:update_order).and_return(true)
allow(payment).to receive(:create_payment_profile).and_return(true)
payment.stub(:update_order)
payment.stub(:create_payment_profile)
end
context "#process!" do

View File

@@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'spec_helper'
describe InjectionHelper, type: :helper, performance: true do
let(:oc) { create(:simple_order_cycle) }
let(:relative_supplier) { create(:supplier_enterprise) }
let(:relative_distributor) { create(:distributor_enterprise) }
before do
50.times do
e = create(:enterprise)
oc.distributors << e
create(:enterprise_relationship, parent: e, child: relative_supplier)
create(:enterprise_relationship, parent: e, child: relative_distributor)
end
end
it "is performant in injecting enterprises" do
results = []
4.times do |i|
ActiveRecord::Base.connection.query_cache.clear
Rails.cache.delete_matched('api\/cached_enterprise_serializer\/enterprises')
result = Benchmark.measure { helper.inject_enterprises }
results << result.total if i.positive?
puts result
end
avg = (results.sum / results.count * 1000).round(0)
puts avg
end
end

View File

@@ -0,0 +1,39 @@
# frozen_string_literal: true
require 'spec_helper'
describe Spree::OrdersController, type: :controller, performance: true do
let(:distributor) { create(:distributor_enterprise) }
let(:order_cycle) {
create(:simple_order_cycle, distributors: [distributor], variants: products.map { |p|
p.variants.first
} )
}
let(:products) { (0...num_products).map { create(:product) } }
let(:order) { subject.current_order(true) }
let(:num_products) { 20 }
before do
order.set_distribution! distributor, order_cycle
controller.stub(:current_order) { order }
Spree::Config.currency = 'AUD'
end
describe "adding products to cart" do
it "adds products to cart" do
puts "Pre-populating first product"
spree_post :populate, variants: { products[0].variants.first.id => 1 }
result = Benchmark.measure do
(1..num_products).each do |num_products|
puts "Populating #{num_products} products"
variants = Hash[products.map { |p| [p.variants.first.id, 1] }.first(num_products)]
spree_post :populate, variants: variants
end
end
puts result
end
end
end

View File

@@ -0,0 +1,50 @@
# frozen_string_literal: true
require 'spec_helper'
describe ShopController, type: :controller, performance: true do
include FileHelper
let(:d) { create(:distributor_enterprise) }
let(:enterprise_fee) { create(:enterprise_fee) }
let(:order_cycle) {
create(:simple_order_cycle, distributors: [d], coordinator_fees: [enterprise_fee])
}
before do
allow(controller).to receive(:current_distributor) { d }
allow(controller).to receive(:current_order_cycle) { order_cycle }
Spree::Config.currency = 'AUD'
end
describe "fetching products" do
let(:exchange) { order_cycle.exchanges.to_enterprises(d).outgoing.first }
let(:image) { white_logo_file }
let(:cache_key_patterns) do
[
'api\/taxon_serializer\/spree\/taxons',
'enterprise'
]
end
before do
11.times do
p = create(:simple_product)
p.set_property 'Organic Certified', 'NASAA 12345'
v1 = create(:variant, product: p)
v2 = create(:variant, product: p)
Spree::Image.create! viewable_id: p.master.id, viewable_type: 'Spree::Variant',
attachment: image
exchange.variants << [v1, v2]
end
end
it "returns products via json" do
results = multi_benchmark(3, cache_key_patterns: cache_key_patterns) do
get :products, xhr: true
expect(response.status).to eq 200
end
end
end
end

View File

@@ -1,21 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
describe BatchTaggableTagsQuery do
it "fetches tags for multiple models in one query" do
customer_i = create(:customer, tag_list: "member,volunteer")
customer_ii = create(:customer, tag_list: "member")
customer_iii = create(:customer, tag_list: nil)
tags = BatchTaggableTagsQuery.call(
Customer.where(id: [customer_i, customer_ii, customer_iii])
)
expect(tags).to eq(
{
customer_i.id => ["member", "volunteer"],
customer_ii.id => ["member"],
}
)
end
end

View File

@@ -3,6 +3,10 @@
require "spec_helper"
describe "routing for Stripe return URLS", type: :routing do
before do
allow_any_instance_of(FeatureToggleConstraint).to receive(:current_user) { build(:user) }
end
context "checkout return URLs" do
it "routes /checkout to checkout#edit" do
expect(get: "checkout").

View File

@@ -5,6 +5,14 @@ require 'base_spec_helper'
require 'database_cleaner'
require 'view_component/test_helpers'
# This spec_helper.rb is being used by the custom engines in engines/. The engines are not set up to
# use Knapsack, and this provides the option to disable it when running the tests in CI services.
unless ENV['DISABLE_KNAPSACK']
require 'knapsack'
Knapsack.tracker.config(enable_time_offset_warning: false) unless ENV['CI']
Knapsack::Adapters::RSpecAdapter.bind
end
Capybara.javascript_driver = :chrome
Capybara.default_max_wait_time = 30
Capybara.disable_animation = true

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
module OpenFoodNetwork
module FeatureToggleHelper
def set_feature_toggle(feature, status)
features = OpenFoodNetwork::FeatureToggle.features
features[feature] = status
allow(OpenFoodNetwork::FeatureToggle).to receive(:features) { features }
end
end
end

View File

@@ -1,48 +0,0 @@
# frozen_string_literal: true
class QueryCounter
QUERY_TYPES = [:delete, :insert, :select, :update].freeze
attr_reader :queries
def initialize
@queries = {}
@subscriber = ActiveSupport::Notifications.
subscribe("sql.active_record") do |_name, _started, _finished, _unique_id, payload|
type = get_type(payload[:sql])
next if QUERY_TYPES.exclude?(type) || pg_query?(payload[:sql])
table = get_table(payload[:sql])
@queries[type] ||= {}
@queries[type][table] ||= 0
@queries[type][table] += 1
end
end
def stop
ActiveSupport::Notifications.unsubscribe("sql.active_record")
end
private
def get_table(sql)
sql_parts = sql.split(" ")
case get_type(sql)
when :insert
sql_parts[3]
when :update
sql_parts[1]
else
table_index = sql_parts.index("FROM")
sql_parts[table_index + 1]
end.gsub(/(\\|")/, "").to_sym
end
def get_type(sql)
sql.split(" ")[0].downcase.to_sym
end
def pg_query?(sql)
sql.include?("SELECT a.attname") || sql.include?("pg_attribute")
end
end

View File

@@ -32,6 +32,5 @@ module AuthenticationHelper
def expect_logged_in
# Ensure page has been reloaded after submitting login form
expect(page).to_not have_selector ".menu #login-link"
expect(page).to_not have_content "Login"
end
end

View File

@@ -28,18 +28,9 @@ module StripeHelper
fill_in "cvc", with: "678"
end
def stripe_enable
def setup_stripe
Stripe.api_key = "sk_test_12345"
Stripe.publishable_key = "pk_test_12345"
allow(Spree::Config).to receive(:stripe_connect_enabled).and_return(true)
end
def with_stripe_setup(api_key = "sk_test_12345", publishable_key = "pk_test_12345")
original_keys = [Stripe.api_key, Stripe.publishable_key]
Stripe.api_key = api_key
Stripe.publishable_key = publishable_key
yield
Stripe.api_key, Stripe.publishable_key = original_keys
end
end

View File

@@ -154,7 +154,7 @@ module WebHelper
def fill_in_tag(tag_name, selector = "tags-input .tags input")
expect(page).to have_selector selector
find(:css, selector).click
find(:css, selector).send_keys ""
find(:css, selector).set "#{tag_name}\n"
expect(page).to have_selector ".tag-list .tag-item span", text: tag_name
end

View File

@@ -9,5 +9,4 @@ VCR.configure do |config|
config.configure_rspec_metadata!
config.filter_sensitive_data('<HIDDEN_KEY>') { ENV['STRIPE_SECRET_TEST_API_KEY'] }
config.filter_sensitive_data('<HIDDEN_CUSTOMER>') { ENV['STRIPE_CUSTOMER'] }
config.ignore_hosts('localhost', '127.0.0.1', '0.0.0.0', 'api.knapsackpro.com')
end

View File

@@ -43,13 +43,12 @@ describe "Taxonomies" do
end
context "edit" do
it "should allow an admin to update an existing taxonomy", retry: 3 do
it "should allow an admin to update an existing taxonomy" do
create(:taxonomy)
click_link "Taxonomies"
within_row(1) { find(".icon-edit").click }
fill_in "taxonomy_name", with: "sports 99"
click_button "Update"
expect(page).to have_current_path spree.admin_taxonomies_path
expect(page).to have_content("successfully updated!")
expect(page).to have_content("sports 99")
end

View File

@@ -5,7 +5,7 @@ require 'system_helper'
describe '
As an administrator
I want to create/update complex order cycles with a specific time
' do
', js: true do
include AdminHelper
include AuthenticationHelper
include WebHelper
@@ -49,7 +49,7 @@ describe '
payment_method_ii.update!(name: "Cash")
end
it "creating an order cycle with full interface", retry: 3 do
it "creating an order cycle with full interface", js: true do
## CREATE
login_as_admin_and_visit admin_order_cycles_path
click_link 'New Order Cycle'

View File

@@ -18,11 +18,9 @@ describe '
create(:stripe_account, enterprise: order.distributor, stripe_user_id: "abc123")
end
around do |example|
with_stripe_setup { example.run }
end
before { setup_stripe }
context "making a new Stripe payment" do
context "making a new Stripe payment", js: true do
before do
stub_payment_methods_post_request
stub_payment_intent_get_request

View File

@@ -7,10 +7,8 @@ describe "Orders And Fulfillment" do
include WebHelper
describe "reports" do
let(:current_user) { create(:admin_user) }
before do
login_to_admin_as(current_user)
login_as_admin
visit admin_reports_path
end
@@ -440,121 +438,5 @@ describe "Orders And Fulfillment" do
end
end
end
describe "Saving report rendering options" do
let(:report_title) { "Order Cycle Supplier Totals" }
let(:second_report_title) { "Order Cycle Supplier Totals by Distributor" }
let(:columns_dropdown_selector) { 'div[data-multiple-checked-select-target="button"]' }
context "Switching between reports" do
context "Display options" do
it "should store display options for every report separately" do
# Step 1: Update report rendering options on two reports
click_link report_title
expect(page).to have_unchecked_field('Header Row')
expect(page).to have_checked_field('Summary Row')
check 'Header Row'
uncheck 'Summary Row'
click_button 'Go'
click_link "Report"
click_link second_report_title
expect(page).to have_unchecked_field('Header Row')
expect(page).to have_checked_field('Summary Row')
check 'Header Row'
click_button 'Go'
# Step 2: check if report rendering options are saved properly
click_link "Report"
click_link report_title
expect(page).to have_checked_field('Header Row')
expect(page).to have_unchecked_field('Summary Row')
click_link "Report"
click_link second_report_title
expect(page).to have_checked_field('Header Row')
expect(page).to have_checked_field('Summary Row')
end
end
context "Columns to show" do
it "should store columns to show for every report separately" do
# Step 1: Update report rendering options on two reports
click_link report_title
find(columns_dropdown_selector).click
expect(page).to have_checked_field('Producer')
expect(page).to have_checked_field('Product')
uncheck('Producer')
uncheck('Product')
click_button 'Go'
click_link "Report"
click_link second_report_title
find(columns_dropdown_selector).click
expect(page).to have_checked_field('Producer')
expect(page).to have_checked_field('Product')
uncheck('Product')
click_button 'Go'
# Step 2: check if report rendering options are saved properly
click_link "Report"
click_link report_title
find(columns_dropdown_selector).click
expect(page).to have_unchecked_field('Producer')
expect(page).to have_unchecked_field('Product')
click_link "Report"
click_link second_report_title
find(columns_dropdown_selector).click
expect(page).to have_checked_field('Producer')
expect(page).to have_unchecked_field('Product')
end
end
end
context "Revisiting a report after logout" do
context "Display options" do
it "should store display options" do
click_link report_title
expect(page).to have_unchecked_field('Header Row')
expect(page).to have_checked_field('Summary Row')
check 'Header Row'
uncheck 'Summary Row'
click_button 'Go'
logout
login_to_admin_as(current_user)
visit admin_reports_path
click_link report_title
expect(page).to have_checked_field('Header Row')
expect(page).to have_unchecked_field('Summary Row')
end
end
context "Columns to show" do
it "should store columns after logout" do
click_link report_title
find(columns_dropdown_selector).click
expect(page).to have_checked_field('Producer')
expect(page).to have_checked_field('Product')
uncheck('Producer')
uncheck('Product')
click_button 'Go'
logout
login_to_admin_as(current_user)
visit admin_reports_path
click_link "Report"
click_link report_title
find(columns_dropdown_selector).click
expect(page).to have_unchecked_field('Producer')
expect(page).to have_unchecked_field('Product')
end
end
end
end
end
end

View File

@@ -83,7 +83,8 @@ describe "As a consumer I want to check out my cart", js: true do
context "split checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).to receive(:enabled?).with(:split_checkout) { true }
allow(OpenFoodNetwork::FeatureToggle).to receive(:enabled?).with(:split_checkout, anything) { true }
end
include_examples "with different checkout types", "split_checkout"
end

View File

@@ -30,12 +30,8 @@ describe "Check out with Stripe", js: true do
calculator: Calculator::FlatRate.new(preferred_amount: 5.67))
}
around do |example|
with_stripe_setup { example.run }
end
before do
stripe_enable
setup_stripe
set_order order
add_product_to_cart order, product
distributor.shipping_methods << [shipping_with_fee, free_shipping]

View File

@@ -65,7 +65,8 @@ describe "As a consumer, I want to checkout my order", js: true do
}
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).to receive(:enabled?).with(:split_checkout).and_return(true)
allow(OpenFoodNetwork::FeatureToggle).to receive(:enabled?).with(:split_checkout, anything).and_return(true)
add_enterprise_fee enterprise_fee
set_order order
@@ -643,12 +644,8 @@ describe "As a consumer, I want to checkout my order", js: true do
end
context "for Stripe SCA", if: pay_method.eql?("Stripe SCA") do
around do |example|
with_stripe_setup { example.run }
end
before do
stripe_enable
setup_stripe
visit checkout_step_path(:payment)
end

View File

@@ -111,7 +111,10 @@ describe "As a consumer, I want to see adjustment breakdown" do
context "on split-checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout).and_return(true)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything).and_return(true)
set_order order_within_zone
login_as(user_within_zone)
@@ -168,7 +171,10 @@ describe "As a consumer, I want to see adjustment breakdown" do
context "on split-checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout).and_return(true)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything).and_return(true)
set_order order_outside_zone
login_as(user_outside_zone)

View File

@@ -118,7 +118,10 @@ describe "As a consumer, I want to see adjustment breakdown" do
context "on split-checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout).and_return(true)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything).and_return(true)
set_order order_within_zone
login_as(user_within_zone)
@@ -178,7 +181,10 @@ describe "As a consumer, I want to see adjustment breakdown" do
context "on split-checkout" do
before do
Flipper.enable(:split_checkout)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout).and_return(true)
allow(OpenFoodNetwork::FeatureToggle).
to receive(:enabled?).with(:split_checkout, anything).and_return(true)
set_order order_outside_zone
login_as(user_outside_zone)

View File

@@ -16,7 +16,7 @@ module CupriteHelpers
# Use our `Capybara.save_path` to store screenshots with other capybara artifacts
# (Rails screenshots path is not configurable https://github.com/rails/rails/blob/49baf092439fc74fc3377b12e3334c3dd9d0752f/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L79)
def absolute_image_path
Rails.root.join("#{Capybara.save_path}/screenshots/#{image_name.parameterize}.png")
Rails.root.join("#{Capybara.save_path}/screenshots/#{image_name}.png")
end
# Make failure screenshots compatible with multi-session setup.

878
yarn.lock

File diff suppressed because it is too large Load Diff