Merge branch '8_increase_test_coverage' into rails_upgrade_tryout

This commit is contained in:
viehlieb 2022-10-13 17:43:15 +02:00
commit 85270e70cf
28 changed files with 1327 additions and 10 deletions

42
.drone.yml Normal file
View file

@ -0,0 +1,42 @@
kind: pipeline
type: docker
name: default
steps:
- name: build and test
image: circleci/ruby:2.6.9-bullseye-node-browsers-legacy
commands:
- sudo apt install --no-install-recommends -y libmagic-dev
- sudo -E bundle install --path /bundle --without production,development
- sudo -E bundle exec rake foodsoft:setup:stock_config || true
- sudo -E bundle exec rake db:schema:load
- sudo -E bundle exec rake rspec-rerun:spec
volumes:
- name: gem-cache
path: /bundle
- name: tmp
path: /drone/src/tmp
environment:
RAILS_LOG_TO_STDOUT: true
RAILS_ENV: test
COVERAGE: lcov
DATABASE_URL: mysql2://user:password@mariadb/test?encoding=utf8mb4
DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: true
PARALLEL_TEST_PROCESSORS: 15
services:
- name: mariadb
image: mariadb
environment:
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: password
volumes:
- name: gem-cache
host:
path: /tmp/cache
- name: tmp
temp: {}

View file

@ -111,6 +111,7 @@ group :test do
gem 'rspec-core'
gem 'rspec-rerun'
gem 'i18n-spec'
gem 'rails-controller-testing'
# code coverage
gem 'simplecov', require: false
gem 'simplecov-lcov', require: false

View file

@ -360,6 +360,10 @@ GEM
sprockets-rails (>= 2.0.0)
rails-assets-listjs (0.2.0.beta.4)
railties (>= 3.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
@ -614,6 +618,7 @@ DEPENDENCIES
rack-cors
rails (~> 6.1)
rails-assets-listjs (= 0.2.0.beta.4)
rails-controller-testing
rails-i18n
rails-settings-cached (= 0.4.3)
rails_tokeninput

View file

@ -22,7 +22,7 @@ class Finance::BalancingController < Finance::BaseController
when 'order_number_reverse' then
@articles.order('articles.order_number DESC')
else
@articles
@articles # TODO: We will never get here
end
render layout: false if request.xhr?
@ -105,6 +105,6 @@ class Finance::BalancingController < Finance::BaseController
end
redirect_to finance_order_index_url, notice: t('finance.balancing.close_all_direct_with_invoice.notice', count: count)
rescue => error
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: error.message)
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: error.message) #TODO: this can't be reached
end
end

View file

@ -63,8 +63,9 @@ class HomeController < ApplicationController
# cancel personal memberships direct from the myProfile-page
def cancel_membership
# TODO: membership_id not used anymore?
if params[:membership_id]
membership = @current_user.memberships.find!(params[:membership_id])
membership = @current_user.memberships.find(params[:membership_id])
else
membership = @current_user.memberships.find_by_group_id!(params[:group_id])
end

View file

@ -7,6 +7,7 @@
default: &defaults
multi_coop_install: false
default_scope: 'f'
tax_default: 0
name: FC Minimal

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
describe ApplicationController, type: :controller do
describe 'current' do
it 'returns current ApplicationController' do
ApplicationController.new.send(:store_controller)
expect(ApplicationController.current).to be_instance_of ApplicationController
end
end
end

View file

@ -0,0 +1,325 @@
# frozen_string_literal: true
require 'spec_helper'
describe ArticlesController, type: :controller do
let(:user) { create :user, :role_article_meta }
let(:article_categoryA) { create :article_category, name: "AAAA" }
let(:article_categoryB) { create :article_category, name: "BBBB" }
let(:articleA) { create :article, name: 'AAAA', note: "AAAA", unit: '250 g', article_category: article_categoryA, availability: false }
let(:articleB) { create :article, name: 'BBBB', note: "BBBB", unit: '500 g', article_category: article_categoryB, availability: true }
let(:articleC) { create :article, name: 'CCCC', note: "CCCC", unit: '500 g', article_category: article_categoryB, availability: true }
let(:supplier) { create :supplier, articles: [articleA, articleB] }
let(:order) { create :order }
before { login user }
describe 'GET index' do
it 'assigns sorting on articles' do
sortings = [
['name', [articleA, articleB]],
['name_reverse', [articleB, articleA]],
['unit', [articleA, articleB]],
['unit_reverse', [articleB, articleA]],
['article_category', [articleA, articleB]],
['article_category_reverse', [articleB, articleA]],
['note', [articleA, articleB]],
['note_reverse', [articleB, articleA]],
['availability', [articleA, articleB]],
['availability_reverse', [articleB, articleA]]
]
sortings.each do |sorting|
get :index, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, sort: sorting[0] }
expect(response).to have_http_status(:success)
expect(assigns(:articles).to_a).to eq(sorting[1])
end
end
it 'triggers an article csv' do
get :index, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }, format: :csv
expect(response.header["Content-Type"]).to include("text/csv")
expect(response.body).to include(articleA.unit, articleB.unit)
end
end
describe "new" do
it 'renders form for a new article' do
get :new, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }, xhr: true
expect(response).to have_http_status(:success)
end
end
describe "copy" do
it 'renders form with copy of an article' do
get :copy, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, article_id: articleA.id }, xhr: true
expect(assigns(:article).attributes).to eq(articleA.dup.attributes)
expect(response).to have_http_status(:success)
end
end
# TODO:
describe "#create" do
it 'creates a new article' do
valid_attributes = articleA.attributes.except("id")
valid_attributes["name"] = "ABAB"
get :create, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, article: valid_attributes }, xhr: true
expect(response).to have_http_status(:success)
end
it 'fails to create a new article and renders #new' do
get :create, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, article: { id: nil } }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('articles/new')
end
end
describe "edit" do
it 'opens form to edit article attributes' do
get :edit, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, id: articleA.id }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('articles/new')
end
end
describe "#edit all" do
it 'renders edit_all' do
get :edit_all, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('articles/edit_all')
end
end
describe "#update" do
it 'updates article attributes' do
get :update, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, id: articleA.id, article: { unit: "300 g" } }, xhr: true
expect(assigns(:article).unit).to eq("300 g")
expect(response).to have_http_status(:success)
end
it 'updates article attributes' do
get :update, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, id: articleA.id, article: { name: nil } }, xhr: true
expect(response).to render_template('articles/new')
end
end
describe "#update_all" do
xit 'updates all articles' do
# never used and controller method bugged
get :update_all, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: [articleA, articleB] }
puts assigns(:articles).count
expect(response).to have_http_status(:success)
end
end
describe "#update_selected" do
let(:order_article) { create :order_article, order: order, article: articleC }
before do
order_article
end
it 'updates selected articles' do
get :update_selected, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, selected_articles: [articleA.id, articleB.id] }
expect(response).to have_http_status(:redirect)
end
it 'destroys selected articles' do
get :update_selected, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, selected_articles: [articleA.id, articleB.id], selected_action: "destroy" }
articleA.reload
articleB.reload
expect(articleA.deleted? && articleB.deleted?).to be_truthy
expect(response).to have_http_status(:redirect)
end
it 'sets availability false on selected articles' do
get :update_selected, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, selected_articles: [articleA.id, articleB.id], selected_action: "setNotAvailable" }
articleA.reload
articleB.reload
expect(articleA.availability || articleB.availability).to be_falsey
expect(response).to have_http_status(:redirect)
end
it 'sets availability true on selected articles' do
get :update_selected, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, selected_articles: [articleA.id, articleB.id], selected_action: "setAvailable" }
articleA.reload
articleB.reload
expect(articleA.availability && articleB.availability).to be_truthy
expect(response).to have_http_status(:redirect)
end
it 'fails deletion if one article is in open order' do
get :update_selected, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, selected_articles: [articleA.id, articleC.id], selected_action: "destroy" }
articleA.reload
articleC.reload
expect(articleA.deleted? || articleC.deleted?).to be_falsey
expect(response).to have_http_status(:redirect)
end
end
describe "#parse_upload" do
# let(:file) { fixture_file_upload(Rails.root.join('spec/fixtures/files/upload_test.csv')) }
# before do
# file
# end
# TODO: Cannot use Rack attributes in controller??
# #<NoMethodError: undefined method `original_filename' for
# "#<Rack::Test::UploadedFile:0x00005575cef1d238>":String
xit 'updates particles from spreadsheet' do
get :parse_upload, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: { file: file, outlist_absent: "1", convert_units: "1" } }
# {articleA.id => articleA, articleB.id => articleB}}
expect(response).to have_http_status(:redirect)
end
end
describe "#sync" do
# TODO: double render error in controller
xit 'updates particles from spreadsheet' do
get :sync, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }
expect(response).to have_http_status(:redirect)
end
end
describe "#destroy" do
let(:order_article) { create :order_article, order: order, article: articleC }
before do
order_article
end
it 'does not delete article if order open' do
get :destroy, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, id: articleC.id }, xhr: true
expect(assigns(:article).deleted?).to be_falsey
expect(response).to have_http_status(:success)
expect(response).to render_template('articles/destroy')
end
it 'deletes article if order closed' do
get :destroy, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, id: articleB.id }, xhr: true
expect(assigns(:article).deleted?).to be_truthy
expect(response).to have_http_status(:success)
expect(response).to render_template('articles/destroy')
end
end
describe "#update_synchronized" do
let(:order_article) { create :order_article, order: order, article: articleC }
before do
order_article
articleA
articleB
articleC
end
it 'deletes articles' do
# TODO: double render error in controller
get :update_synchronized, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, outlisted_articles: { articleA.id => articleA, articleB.id => articleB } }
articleA.reload
articleB.reload
expect(articleA.deleted? && articleB.deleted?).to be_truthy
expect(response).to have_http_status(:redirect)
end
it 'updates articles' do
get :update_synchronized, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: { articleA.id => { name: "NewNameA" }, articleB.id => { name: "NewNameB" } } }
expect(assigns(:updated_articles).first.name).to eq "NewNameA"
expect(response).to have_http_status(:redirect)
end
it 'does not update articles if article with same name exists' do
get :update_synchronized, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: { articleA.id => { unit: "2000 g" }, articleB.id => { name: "AAAA" } } }
error_array = [assigns(:updated_articles).first.errors.first, assigns(:updated_articles).last.errors.first]
expect(error_array).to include([:name, "name is already taken"])
expect(response).to have_http_status(:success)
end
it 'does update articles if article with same name was deleted before' do
get :update_synchronized, params: {
foodcoop: FoodsoftConfig[:default_scope],
supplier_id: supplier.id,
outlisted_articles: { articleA.id => articleA },
articles: {
articleA.id => { name: "NewName" },
articleB.id => { name: "AAAA" }
}
}
error_array = [assigns(:updated_articles).first.errors.first, assigns(:updated_articles).last.errors.first]
expect(error_array.any?).to be_falsey
expect(response).to have_http_status(:redirect)
end
it 'does not delete articles in open order' do
get :update_synchronized, params: {
foodcoop: FoodsoftConfig[:default_scope],
supplier_id: supplier.id,
outlisted_articles: { articleC.id => articleC }
}
articleC.reload
expect(articleC.deleted?).to be_falsey
expect(response).to have_http_status(:success)
end
it 'assigns updated article_pairs on error' do
get :update_synchronized, params: {
foodcoop: FoodsoftConfig[:default_scope],
supplier_id: supplier.id,
articles: { articleA.id => { name: "DDDD" } },
outlisted_articles: { articleC.id => articleC }
}
expect(assigns(:updated_article_pairs).first).to eq([articleA, { name: "DDDD" }])
articleC.reload
expect(articleC.deleted?).to be_falsey
expect(response).to have_http_status(:success)
end
it 'updates articles in open order' do
get :update_synchronized, params: {
foodcoop: FoodsoftConfig[:default_scope],
supplier_id: supplier.id,
articles: { articleC.id => { name: "DDDD" } }
}
articleC.reload
expect(articleC.name).to eq "DDDD"
expect(response).to have_http_status(:redirect)
end
end
describe "#shared" do
let(:shared_supplier) { create :shared_supplier, shared_articles: [shared_article] }
let(:shared_article) { create :shared_article, name: "shared" }
let(:articleS) { create :article, name: 'SSSS', note: "AAAA", unit: '250 g', article_category: article_categoryA, availability: false }
let(:supplier_with_shared) { create :supplier, articles: [articleS], shared_supplier: shared_supplier }
it 'renders view with articles' do
get :shared, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier_with_shared.id, name_cont_all_joined: "shared" }, xhr: true
expect(assigns(:supplier).shared_supplier.shared_articles.any?).to be_truthy
expect(assigns(:articles).any?).to be_truthy
expect(response).to have_http_status(:success)
end
end
describe "#import" do
let(:shared_supplier) { create :shared_supplier, shared_articles: [shared_article] }
let(:shared_article) { create :shared_article, name: "shared" }
before do
shared_article
article_categoryA
end
it 'fills form with article details' do
get :import, params: { foodcoop: FoodsoftConfig[:default_scope], article_category_id: article_categoryB.id, direct: "true", supplier_id: supplier.id, shared_article_id: shared_article.id }, xhr: true
expect(assigns(:article).nil?).to be_falsey
expect(response).to have_http_status(:success)
expect(response).to render_template(:create)
end
it 'does redirect to :new if param :direct not set' do
get :import, params: { foodcoop: FoodsoftConfig[:default_scope], article_category_id: article_categoryB.id, supplier_id: supplier.id, shared_article_id: shared_article.id }, xhr: true
expect(assigns(:article).nil?).to be_falsey
expect(response).to have_http_status(:success)
expect(response).to render_template(:new)
end
end
end

View file

@ -0,0 +1,184 @@
# frozen_string_literal: true
require 'spec_helper'
class DummyAuthController < ApplicationController; end
describe 'Auth concern', type: :controller do
controller DummyAuthController do
# Defining a dummy action for an anynomous controller which inherits from the described class.
def authenticate_blank
authenticate
end
def authenticate_unknown_group
authenticate('nooby')
end
def authenticate_pickups
authenticate('pickups')
head :ok unless performed?
end
def authenticate_finance_or_orders
authenticate('finance_or_orders')
head :ok unless performed?
end
def try_authenticate_membership_or_admin
authenticate_membership_or_admin
end
def try_authenticate_or_token
authenticate_or_token('xyz')
head :ok unless performed?
end
end
# unit testing protected/private methods
describe 'protected/private methods' do
let(:user) { create :user }
describe '#current_user' do
before { login user }
describe 'with valid session' do
it "returns current_user" do
subject.session[:user_id] = user.id
subject.params[:foodcoop] = FoodsoftConfig[:default_scope]
expect(subject.send(:current_user)).to eq user
expect(assigns(:current_user)).to eq user
end
end
describe 'with invalid session' do
it "not returns current_user" do
subject.session[:user_id] = ''
subject.params[:foodcoop] = FoodsoftConfig[:default_scope]
expect(subject.send(:current_user)).to be_nil
expect(assigns(:current_user)).to be_nil
end
end
end
describe '#deny_access' do
xit "redirects to root_url" do
expect(subject.send(:deny_access)).to redirect_to(root_url)
end
end
describe '#login' do
it "sets user in session" do
subject.send(:login, user)
expect(subject.session[:user_id]).to eq user.id
expect(subject.session[:scope]).to eq FoodsoftConfig.scope
expect(subject.session[:locale]).to eq user.locale
end
end
describe '#login_and_redirect_to_return_to' do
xit "redirects to already set target" do
subject.session[:return_to] = my_profile_url
subject.send(:login_and_redirect_to_return_to, user)
expect(subject.session[:return_to]).to be nil
end
end
end
describe 'authenticate' do
describe 'not logged in' do
it 'does not authenticate' do
routes.draw { get "authenticate_blank" => "dummy_auth#authenticate_blank" }
get :authenticate_blank, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_path)
expect(flash[:alert]).to match(I18n.t('application.controller.error_authn'))
end
end
describe 'logged in' do
let(:user) { create :user }
let(:pickups_user) { create :user, :role_pickups }
let(:finance_user) { create :user, :role_finance }
let(:orders_user) { create :user, :role_orders }
it 'does not authenticate with unknown group' do
login user
routes.draw { get "authenticate_unknown_group" => "dummy_auth#authenticate_unknown_group" }
get :authenticate_unknown_group, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to match(I18n.t('application.controller.error_denied', sign_in: ActionController::Base.helpers.link_to(I18n.t('application.controller.error_denied_sign_in'), login_path)))
end
it 'does not authenticate with pickups group' do
login pickups_user
routes.draw { get "authenticate_pickups" => "dummy_auth#authenticate_pickups" }
get :authenticate_pickups, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
end
it 'does not authenticate with finance group' do
login finance_user
routes.draw { get "authenticate_finance_or_orders" => "dummy_auth#authenticate_finance_or_orders" }
get :authenticate_finance_or_orders, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
end
it 'does not authenticate with orders group' do
login orders_user
routes.draw { get "authenticate_finance_or_orders" => "dummy_auth#authenticate_finance_or_orders" }
get :authenticate_finance_or_orders, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
end
end
end
describe 'authenticate_membership_or_admin' do
describe 'logged in' do
let(:pickups_user) { create :user, :role_pickups }
let(:workgroup) { create :workgroup }
it 'redirects with not permitted group' do
group_id = workgroup.id
login pickups_user
routes.draw { get "try_authenticate_membership_or_admin" => "dummy_auth#try_authenticate_membership_or_admin" }
get :try_authenticate_membership_or_admin, params: { foodcoop: FoodsoftConfig[:default_scope], id: group_id }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to match(I18n.t('application.controller.error_members_only'))
end
end
end
describe 'authenticate_or_token' do
describe 'logged in' do
let(:token_verifier) { TokenVerifier.new('xyz') }
let(:token_msg) { token_verifier.generate }
let(:user) { create :user }
it 'authenticates token' do
login user
routes.draw { get "try_authenticate_or_token" => "dummy_auth#try_authenticate_or_token" }
get :try_authenticate_or_token, params: { foodcoop: FoodsoftConfig[:default_scope], token: token_msg }
expect(response).to_not have_http_status(:redirect)
end
it 'redirects on faulty token' do
login user
routes.draw { get "try_authenticate_or_token" => "dummy_auth#try_authenticate_or_token" }
get :try_authenticate_or_token, params: { foodcoop: FoodsoftConfig[:default_scope], token: 'abc' }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to match(I18n.t('application.controller.error_token'))
end
it 'authenticates current user on empty token' do
login user
routes.draw { get "try_authenticate_or_token" => "dummy_auth#try_authenticate_or_token" }
get :try_authenticate_or_token, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
end
end
end
end

View file

@ -0,0 +1,212 @@
# frozen_string_literal: true
require 'spec_helper'
describe Finance::BalancingController, type: :controller do
let(:user) { create :user, :role_finance, :role_orders, groups: [create(:ordergroup)] }
before { login user }
describe 'GET index' do
let(:order) { create :order }
it 'renders index page' do
get :index, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/index')
end
end
describe 'new balancing' do
let(:supplier) { create :supplier }
let(:article1) { create :article, name: "AAAA", supplier: supplier, unit_quantity: 1 }
let(:article2) { create :article, name: "AAAB", supplier: supplier, unit_quantity: 1 }
let(:order) { create :order, supplier: supplier, article_ids: [article1.id, article2.id] }
let(:go1) { create :group_order, order: order }
let(:go2) { create :group_order, order: order }
let(:oa1) { order.order_articles.find_by_article_id(article1.id) }
let(:oa2) { order.order_articles.find_by_article_id(article2.id) }
let(:oa3) { order2.order_articles.find_by_article_id(article2.id) }
let(:goa1) { create :group_order_article, group_order: go1, order_article: oa1 }
let(:goa2) { create :group_order_article, group_order: go1, order_article: oa2 }
before do
goa1.update_quantities(3, 0)
goa2.update_quantities(1, 0)
oa1.update_results!
oa2.update_results!
end
it 'renders new order page' do
get :new, params: { foodcoop: FoodsoftConfig[:default_scope], order_id: order.id }
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/new')
end
it 'assigns sorting on articles' do
sortings = [
['name', [oa1, oa2]],
['name_reverse', [oa2, oa1]],
['order_number', [oa1, oa2]],
['order_number_reverse', [oa1, oa2]] # just one order
]
sortings.each do |sorting|
get :new, params: { foodcoop: FoodsoftConfig[:default_scope], order_id: order.id, sort: sorting[0] }
expect(response).to have_http_status(:success)
expect(assigns(:articles).to_a).to eq(sorting[1])
end
end
end
describe 'update summary' do
let(:order) { create(:order) }
it 'shows the summary view' do
get :update_summary, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/update_summary')
end
end
describe 'new_on_order' do
let(:order) { create(:order) }
let(:order_article) { order.order_articles.first }
# TODO: how to check for js.erb calls?
it 'calls article update' do
get :new_on_order_article_update, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order_article_id: order_article.id }, xhr: true
expect(response).not_to render_template(layout: "application")
expect(response).to render_template('finance/balancing/new_on_order_article_update')
end
it 'calls article create' do
get :new_on_order_article_create, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order_article_id: order_article.id }, xhr: true
expect(response).not_to render_template(layout: "application")
expect(response).to render_template('finance/balancing/new_on_order_article_create')
end
end
describe 'edit_note' do
let(:order) { create(:order) }
it 'updates order note' do
get :edit_note, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order: { note: "Hello" } }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/edit_note')
end
end
describe 'update_note' do
let(:order) { create(:order) }
it 'updates order note' do
get :update_note, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order: { note: "Hello" } }, xhr: true
expect(response).to have_http_status(:success)
end
it 'redirects to edit note on failed update' do
get :update_note, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order: { article_ids: nil } }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/edit_note')
end
end
describe 'transport' do
let(:order) { create(:order) }
it 'calls the edit transport view' do
get :edit_transport, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/edit_transport')
end
it 'does redirect if order valid' do
get :update_transport, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order: { ends: Time.now } }, xhr: true
expect(response).to have_http_status(:redirect)
expect(assigns(:order).errors.count).to eq(0)
expect(response).to redirect_to(new_finance_order_path(order_id: order.id))
end
it 'does redirect if order invalid' do
get :update_transport, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, order: { starts: Time.now + 2, ends: Time.now } }, xhr: true
expect(assigns(:order).errors.count).to eq(1)
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(new_finance_order_path(order_id: order.id))
end
end
describe 'confirm' do
let(:order) { create(:order) }
it 'renders the confirm template' do
get :confirm, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id }, xhr: true
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/balancing/confirm')
end
end
describe 'close and update account balances' do
let(:order) { create(:order) }
let(:order1) { create(:order, ends: Time.now) }
let(:fft) { create(:financial_transaction_type) }
it 'does not close order if ends not set' do
get :close, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id, type: fft.id }
expect(assigns(:order).closed?).to be_falsey
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(new_finance_order_url(order_id: order.id))
end
it 'closes order' do
get :close, params: { foodcoop: FoodsoftConfig[:default_scope], id: order1.id, type: fft.id }
expect(assigns(:order).closed?).to be_truthy
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(finance_order_index_url)
end
end
describe 'close direct' do
let(:order) { create(:order) }
it 'does not close order if already closed' do
order.close_direct!(user)
get :close_direct, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id }
expect(assigns(:order).closed?).to be_truthy
end
it 'closes order directly' do
get :close_direct, params: { foodcoop: FoodsoftConfig[:default_scope], id: order.id }
expect(assigns(:order).closed?).to be_truthy
end
end
describe 'close all direct' do
let(:invoice) { create(:invoice) }
let(:invoice1) { create(:invoice) }
let(:order) { create(:order, state: 'finished', ends: Time.now + 2.hours, invoice: invoice) }
let(:order1) { create(:order, state: 'finished', ends: Time.now + 2.hours) }
before do
order
order1
end
it 'does close orders' do
get :close_all_direct_with_invoice, params: { foodcoop: FoodsoftConfig[:default_scope] }
order.reload
expect(order.closed?).to be_truthy
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(finance_order_index_url)
end
it 'does not close orders when invoice not set' do
get :close_all_direct_with_invoice, params: { foodcoop: FoodsoftConfig[:default_scope] }
order1.reload
expect(order1.closed?).to be_falsey
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(finance_order_index_url)
end
end
end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'spec_helper'
describe Finance::BaseController, type: :controller do
let(:user) { create :user, :role_finance, :role_orders, :ordergroup }
before { login user }
describe 'GET index' do
let(:fin_trans) { create_list :financial_transaction, 3, user: user, ordergroup: user.ordergroup }
let(:orders) { create_list :order, 2, state: 'finished' }
let(:invoices) { create_list :invoice, 4 }
before do
fin_trans
orders
invoices
end
it 'renders index page' do
get :index, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
expect(response).to render_template('finance/index')
expect(assigns(:financial_transactions).size).to eq(fin_trans.size)
expect(assigns(:orders).size).to eq(orders.size)
expect(assigns(:unpaid_invoices).size).to eq(invoices.size)
end
end
end

View file

@ -0,0 +1,189 @@
# frozen_string_literal: true
require 'spec_helper'
describe HomeController, type: :controller do
let(:user) { create :user }
describe 'GET index' do
describe 'NOT logged in' do
it 'redirects' do
get :profile, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_path)
end
end
describe 'logegd in' do
before { login user }
it 'assigns tasks' do
get :index, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(assigns(:unaccepted_tasks)).not_to be_nil
expect(assigns(:next_tasks)).not_to be_nil
expect(assigns(:unassigned_tasks)).not_to be_nil
expect(response).to render_template('home/index')
end
end
end
describe 'GET profile' do
before { login user }
it 'renders dashboard' do
get :profile, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
expect(response).to render_template('home/profile')
end
end
describe 'GET reference_calculator' do
describe 'with simple user' do
before { login user }
it 'redirects to home' do
get :reference_calculator, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(root_path)
end
end
describe 'with ordergroup user' do
let(:og_user) { create :user, :ordergroup }
before { login og_user }
it 'renders reference calculator' do
get :reference_calculator, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
expect(response).to render_template('home/reference_calculator')
end
end
end
describe 'GET update_profile' do
describe 'with simple user' do
let(:unchanged_attributes) { user.attributes.slice('first_name', 'last_name', 'email') }
let(:changed_attributes) { attributes_for :user }
let(:invalid_attributes) { { email: 'e.mail.com' } }
before { login user }
it 'renders profile after update with invalid attributes' do
get :update_profile, params: { foodcoop: FoodsoftConfig[:default_scope], user: invalid_attributes }
expect(response).to have_http_status(:success)
expect(response).to render_template('home/profile')
expect(assigns(:current_user).errors.present?).to be true
end
it 'redirects to profile after update with unchanged attributes' do
get :update_profile, params: { foodcoop: FoodsoftConfig[:default_scope], user: unchanged_attributes }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
end
it 'redirects to profile after update' do
patch :update_profile, params: { foodcoop: FoodsoftConfig[:default_scope], user: changed_attributes }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
expect(flash[:notice]).to match(/#{I18n.t('home.changes_saved')}/)
expect(user.reload.attributes.slice(:first_name, :last_name, :email)).to eq(changed_attributes.slice('first_name', 'last_name', 'email'))
end
end
describe 'with ordergroup user' do
let(:og_user) { create :user, :ordergroup }
let(:unchanged_attributes) { og_user.attributes.slice('first_name', 'last_name', 'email') }
let(:changed_attributes) { unchanged_attributes.merge({ ordergroup: { contact_address: 'new Adress 7' } }) }
before { login og_user }
it 'redirects to home after update' do
get :update_profile, params: { foodcoop: FoodsoftConfig[:default_scope], user: changed_attributes }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
expect(og_user.reload.ordergroup.contact_address).to eq('new Adress 7')
end
end
end
describe 'GET ordergroup' do
describe 'with simple user' do
before { login user }
it 'redirects to home' do
get :ordergroup, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(root_path)
end
end
describe 'with ordergroup user' do
let(:og_user) { create :user, :ordergroup }
before { login og_user }
it 'renders ordergroup' do
get :ordergroup, params: { foodcoop: FoodsoftConfig[:default_scope] }
expect(response).to have_http_status(:success)
expect(response).to render_template('home/ordergroup')
end
describe 'assigns sortings' do
let(:fin_trans1) { create :financial_transaction, user: og_user, ordergroup: og_user.ordergroup, note: 'A', amount: 100 }
let(:fin_trans2) { create :financial_transaction, user: og_user, ordergroup: og_user.ordergroup, note: 'B', amount: 200, created_on: Time.now + 1.minute }
before do
fin_trans1
fin_trans2
end
it 'by criteria' do
sortings = [
['date', [fin_trans1, fin_trans2]],
['note', [fin_trans1, fin_trans2]],
['amount', [fin_trans1, fin_trans2]],
['date_reverse', [fin_trans2, fin_trans1]],
['note_reverse', [fin_trans2, fin_trans1]],
['amount_reverse', [fin_trans2, fin_trans1]]
]
sortings.each do |sorting|
get :ordergroup, params: { foodcoop: FoodsoftConfig[:default_scope], sort: sorting[0] }
expect(response).to have_http_status(:success)
expect(assigns(:financial_transactions).to_a).to eq(sorting[1])
end
end
end
end
end
describe 'GET cancel_membership' do
describe 'with simple user without group' do
before { login user }
it 'fails' do
expect do
get :cancel_membership, params: { foodcoop: FoodsoftConfig[:default_scope] }
end.to raise_error(ActiveRecord::RecordNotFound)
end
end
describe 'with ordergroup user' do
let(:fin_user) { create :user, :role_finance }
before { login fin_user }
it 'removes user from group' do
membership = fin_user.memberships.first
get :cancel_membership,
params: { foodcoop: FoodsoftConfig[:default_scope],
group_id: fin_user.groups.first.id }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
expect(flash[:notice]).to match(/#{I18n.t('home.ordergroup_cancelled', :group => membership.group.name)}/)
end
end
end
end

View file

@ -0,0 +1,67 @@
# frozen_string_literal: true
require 'spec_helper'
describe LoginController, type: :controller do
let(:invite) { create :invite }
describe 'GET accept_invitation' do
let(:expired_invite) { create :expired_invite }
describe 'with valid token' do
it 'accepts invitation' do
get :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: invite.token }
expect(response).to have_http_status(:success)
expect(response).to render_template('login/accept_invitation')
end
end
describe 'with invalid token' do
it 'redirects to login' do
get :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: invite.token + 'XX' }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_url)
expect(flash[:alert]).to match(I18n.t('login.controller.error_invite_invalid'))
end
end
describe 'with timed out token' do
it 'redirects to login' do
get :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: expired_invite.token }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_url)
expect(flash[:alert]).to match(I18n.t('login.controller.error_invite_invalid'))
end
end
describe 'without group' do
it 'redirects to login' do
invite.group.destroy
get :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: invite.token }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_url)
expect(flash[:alert]).to match(I18n.t('login.controller.error_group_invalid'))
end
end
end
describe 'POST accept_invitation' do
describe 'with invalid parameters' do
it 'renders accept_invitation view' do
post :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: invite.token, user: invite.user.slice('first_name') }
expect(response).to have_http_status(:success)
expect(response).to render_template('login/accept_invitation')
expect(assigns(:user).errors.present?).to be true
end
end
describe 'with valid parameters' do
it 'redirects to login' do
post :accept_invitation, params: { foodcoop: FoodsoftConfig[:default_scope], token: invite.token, user: invite.user.slice('first_name', 'password') }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(login_url)
expect(flash[:notice]).to match(I18n.t('login.controller.accept_invitation.notice'))
end
end
end
end

View file

@ -0,0 +1,9 @@
require 'factory_bot'
FactoryBot.define do
factory :delivery do
supplier { create :supplier }
invoice { create :invoice }
date { Faker::Date.backward(days: 14) }
end
end

15
spec/factories/invite.rb Normal file
View file

@ -0,0 +1,15 @@
require 'factory_bot'
FactoryBot.define do
factory :invite do
user { create :user }
group { create :group }
email { Faker::Internet.email }
factory :expired_invite do
after :create do |invite|
invite.update_column(:expires_at, Time.now.yesterday)
end
end
end
end

View file

@ -0,0 +1,8 @@
require 'factory_bot'
FactoryBot.define do
factory :order_article do
order { create :order }
article { create :article }
end
end

View file

@ -5,6 +5,7 @@ FactoryBot.define do
name { Faker::Company.name.truncate(30) }
phone { Faker::PhoneNumber.phone_number }
address { Faker::Address.street_address }
email { Faker::Internet.email }
transient do
article_count { 0 }

3
spec/fixtures/files/upload_test.csv vendored Normal file
View file

@ -0,0 +1,3 @@
avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Unit quantity;"";"";Category
"";;AAAA;AAAA;;;500 g;25.55;6.0;0.0;1;"";"";AAAA
"";;BBBB;BBBB;;;250 g;12.11;6.0;0.0;2;"";"";BBBB
1 avail. Order number Name Note Manufacturer Origin Unit Price (net) VAT Deposit Unit quantity Category
2 AAAA AAAA 500 g 25.55 6.0 0.0 1 AAAA
3 BBBB BBBB 250 g 12.11 6.0 0.0 2 BBBB

3
spec/fixtures/upload_test.csv vendored Normal file
View file

@ -0,0 +1,3 @@
avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Unit quantity;"";"";Category
"";;AAAA;AAAA;;;500 g;25.55;6.0;0.0;1;"";"";AAAA
"";;BBBB;BBBB;;;250 g;12.11;6.0;0.0;2;"";"";BBBB
1 avail. Order number Name Note Manufacturer Origin Unit Price (net) VAT Deposit Unit quantity Category
2 AAAA AAAA 500 g 25.55 6.0 0.0 1 AAAA
3 BBBB BBBB 250 g 12.11 6.0 0.0 2 BBBB

View file

@ -0,0 +1,29 @@
require_relative '../spec_helper'
feature Admin::BaseController do
let(:admin) { create :admin }
let(:users) { create_list :user, 2 }
let(:workgroups) { create_list :workgroup, 3 }
let(:groups) { create_list :group, 4 }
before { login admin }
describe 'base#index' do
before do
users
end
it 'is accessible with workgroups existing' do
workgroups
visit admin_root_path
expect(page).to have_content(I18n.t('admin.base.index.newest_users'))
expect(page).to have_content(users.first.name)
end
# TODO:
it 'raising error when groups existing' do
groups
expect{ visit admin_root_path }.to raise_error(ActionView::Template::Error)
end
end
end

View file

@ -0,0 +1,23 @@
require_relative '../spec_helper'
feature HomeController do
let(:user) { create :user }
before { login user }
describe 'my profile' do
before { visit my_profile_path }
it 'is accessible' do
expect(page).to have_selector 'input[id=user_first_name]'
expect(find_field('user_first_name').value).to eq(user.first_name)
end
it 'updates first name' do
fill_in 'user_first_name', with: 'foo'
click_button('Save')
expect(User.find(user.id).first_name).to eq 'foo'
expect(page).to have_selector '.alert-success'
end
end
end

View file

@ -2,12 +2,11 @@ require_relative '../spec_helper'
feature 'supplier' do
let(:supplier) { create :supplier }
describe 'create new' do
let(:user) { create :user, groups: [create(:workgroup, role_suppliers: true)] }
before { login user }
describe 'create new' do
it 'can be created' do
create :supplier_category
visit suppliers_path
@ -28,4 +27,36 @@ feature 'supplier' do
expect(page).to have_content(supplier.name)
end
end
describe 'existing', js: true do
it 'can be shown' do
supplier
visit suppliers_path
click_link supplier.name
expect(page).to have_content(supplier.address)
expect(page).to have_content(supplier.phone)
expect(page).to have_content(supplier.email)
end
it 'can be updated' do
new_name = Faker::Company.name.truncate(30)
supplier
visit suppliers_path
click_link I18n.t('ui.edit')
fill_in I18n.t('activerecord.attributes.supplier.name'), with: new_name
click_button 'Update Supplier'
expect(supplier.reload.name).to eq new_name
end
it 'can be destroyed' do
supplier
visit suppliers_path
expect(page).to have_content(supplier.name)
accept_confirm do
click_link I18n.t('ui.delete')
end
expect(page).not_to have_content(supplier.name)
expect(supplier.reload.deleted?).to be true
end
end
end

View file

@ -9,6 +9,38 @@ describe Article do
expect(article2).to be_invalid
end
it 'can be deleted' do
article.mark_as_deleted()
expect(article.deleted?).to be true
end
describe 'convert units' do
it 'returns nil when equal' do expect(article.convert_units(article)).to be nil end
it 'returns false when invalid unit' do
article1 = build :article, supplier: supplier, unit: "invalid"
expect(article.convert_units(article1)).to be false
end
it 'converts from ST to KI' do
article1 = build :article, supplier: supplier, unit: "ST"
article2 = build :article, supplier: supplier, name: "banana 10-12 St", price: 12.34, unit: "KI"
new_price, new_unit_quantity = article1.convert_units(article2)
expect(new_unit_quantity).to eq 10
expect(new_price).to eq 1.23
end
it 'converts from g to kg' do
article1 = build :article, supplier: supplier, unit: "kg"
article2 = build :article, supplier: supplier, unit: "g", price: 0.12, unit_quantity: 1500
new_price, new_unit_quantity = article1.convert_units(article2)
expect(new_unit_quantity).to eq 1.5
expect(new_price).to eq 120
end
end
it 'computes changed article attributes' do # not done yet!
article2 = build :article, supplier: supplier, name: "banana"
expect(article.unequal_attributes(article2)[:name]).to eq "banana"
end
it 'computes the gross price correctly' do
article.deposit = 0
article.tax = 12

View file

@ -0,0 +1,23 @@
require_relative '../spec_helper'
describe Delivery do
let(:delivery) { create :delivery }
let(:stock_article) { create :stock_article, price: 3 }
it 'creates new stock_changes' do
delivery.new_stock_changes = ([
{
quantity: 1,
stock_article: stock_article
},
{
quantity: 2,
stock_article: stock_article
}
])
expect(delivery.stock_changes.last[:stock_article_id]).to be stock_article.id
expect(delivery.includes_article?(stock_article)).to be true
expect(delivery.sum(:net)).to eq 9
end
end

View file

@ -40,13 +40,22 @@ describe GroupOrderArticle do
goa.update_quantities(0, 0)
expect(GroupOrderArticle.exists?(goa.id)).to be false
end
it 'updates quantity and tolerance' do
goa.update_quantities(2,2)
goa.update_quantities(1,1)
expect(goa.quantity).to eq(1)
expect(goa.tolerance).to eq(1)
goa.update_quantities(1,2)
expect(goa.tolerance).to eq(2)
end
end
describe 'distribution strategy' do
let(:article) { create :article, supplier: order.supplier, unit_quantity: 1 }
let(:oa) { order.order_articles.create(:article => article) }
let(:goa) { create :group_order_article, group_order: go, order_article: oa }
let!(:goaq) { create :group_order_article_quantity, group_order_article: goa, quantity: 4 }
let!(:goaq) { create :group_order_article_quantity, group_order_article: goa, quantity: 4, tolerance: 6}
it 'can calculate the result for the distribution strategy "first order first serve"' do
res = goa.calculate_result(2)
@ -55,9 +64,13 @@ describe GroupOrderArticle do
it 'can calculate the result for the distribution strategy "no automatic distribution"' do
FoodsoftConfig[:distribution_strategy] = FoodsoftConfig::DistributionStrategy::NO_AUTOMATIC_DISTRIBUTION
res = goa.calculate_result(2)
expect(res).to eq(quantity: 4, tolerance: 0, total: 4)
end
it 'determines tolerance correctly' do
res = goa.calculate_result(6)
expect(res).to eq(quantity: 4, tolerance: 2, total: 6)
end
end
end

View file

@ -3,6 +3,35 @@ require_relative '../spec_helper'
describe Supplier do
let(:supplier) { create :supplier }
context 'syncs from file' do
it 'imports and updates articles' do
article1 = create(:article, supplier: supplier, order_number: 177813, unit: '250 g', price: 0.1)
article2 = create(:article, supplier: supplier, order_number: 12345)
supplier.articles = [article1, article2]
options = { filename: "foodsoft_file_01.csv" }
options[:outlist_absent] = true
options[:convert_units] = true
updated_article_pairs, outlisted_articles, new_articles = supplier.sync_from_file( Rails.root.join("spec/fixtures/foodsoft_file_01.csv"), options)
expect(new_articles.length).to be > 0
expect(updated_article_pairs.first[1][:name]).to eq "Tomaten"
expect(outlisted_articles.first).to eq article2
end
end
it 'return correct tolerance' do
supplier = create :supplier, articles: create_list(:article, 1, unit_quantity: 1)
expect(supplier.has_tolerance?).to be false
supplier2 = create :supplier, articles: create_list(:article, 1, unit_quantity: 2)
expect(supplier2.has_tolerance?).to be true
end
it 'deletes the supplier and its articles' do
supplier = create :supplier, article_count: 3
supplier.articles.each{ |a| expect(a).to receive(:mark_as_deleted) }
supplier.mark_as_deleted
expect(supplier.deleted?).to be(true)
end
it 'has a unique name' do
supplier2 = build :supplier, name: supplier.name
expect(supplier2).to be_invalid

View file

@ -21,6 +21,10 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
# We use capybara with webkit, and need database_cleaner
# config.before(:suite) do
# DatabaseCleaner.clean_with(:truncation)
# end
config.before(:each) do
DatabaseCleaner.strategy = (RSpec.current_example.metadata[:js] ? :truncation : :transaction)
DatabaseCleaner.start
@ -51,8 +55,8 @@ RSpec.configure do |config|
# --seed 1234
config.order = "random"
config.include SpecTestHelper, type: :controller
config.include SessionHelper, type: :feature
# Automatically determine spec from directory structure, see:
# https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/directory-structure
config.infer_spec_type_from_file_location!

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
# spec/support/spec_test_helper.rb
module SpecTestHelper
def login_admin
login(:admin)
end
def login(user)
user = User.where(:nick => user.nick).first if user.is_a?(Symbol)
session[:user_id] = user.id
session[:scope] = FoodsoftConfig[:default_scope] # Save scope in session to not allow switching between foodcoops with one account
session[:locale] = user.locale
end
def current_user
User.find(session[:user_id])
end
end
# spec/spec_helper.rb
RSpec.configure do |config|
config.include SpecTestHelper, :type => :controller
end