8_increase_test_coverage_controllers #36
16 changed files with 1140 additions and 4 deletions
1
Gemfile
1
Gemfile
|
@ -112,6 +112,7 @@ group :test do
|
||||||
gem 'rspec-core'
|
gem 'rspec-core'
|
||||||
gem 'rspec-rerun'
|
gem 'rspec-rerun'
|
||||||
gem 'i18n-spec'
|
gem 'i18n-spec'
|
||||||
|
gem 'rails-controller-testing'
|
||||||
# code coverage
|
# code coverage
|
||||||
gem 'simplecov', require: false
|
gem 'simplecov', require: false
|
||||||
gem 'simplecov-lcov', require: false
|
gem 'simplecov-lcov', require: false
|
||||||
|
|
|
@ -350,6 +350,10 @@ GEM
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-assets-listjs (0.2.0.beta.4)
|
rails-assets-listjs (0.2.0.beta.4)
|
||||||
railties (>= 3.1)
|
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)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
|
@ -606,6 +610,7 @@ DEPENDENCIES
|
||||||
rack-cors
|
rack-cors
|
||||||
rails (~> 5.2)
|
rails (~> 5.2)
|
||||||
rails-assets-listjs (= 0.2.0.beta.4)
|
rails-assets-listjs (= 0.2.0.beta.4)
|
||||||
|
rails-controller-testing
|
||||||
rails-i18n
|
rails-i18n
|
||||||
rails-settings-cached (= 0.4.3)
|
rails-settings-cached (= 0.4.3)
|
||||||
rails_tokeninput
|
rails_tokeninput
|
||||||
|
|
|
@ -18,7 +18,7 @@ class HomeController < ApplicationController
|
||||||
@bank_accounts = @types.includes(:bank_account).map(&:bank_account).uniq.compact
|
@bank_accounts = @types.includes(:bank_account).map(&:bank_account).uniq.compact
|
||||||
@bank_accounts = [BankAccount.last] if @bank_accounts.empty?
|
@bank_accounts = [BankAccount.last] if @bank_accounts.empty?
|
||||||
else
|
else
|
||||||
redirect_to root_url, alert: I18n.t('group_orders.errors.no_member')
|
redirect_to root_path, alert: I18n.t('group_orders.errors.no_member')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class HomeController < ApplicationController
|
||||||
if @current_user.update(user_params)
|
if @current_user.update(user_params)
|
||||||
@current_user.ordergroup.update(ordergroup_params) if ordergroup_params
|
@current_user.ordergroup.update(ordergroup_params) if ordergroup_params
|
||||||
session[:locale] = @current_user.locale
|
session[:locale] = @current_user.locale
|
||||||
redirect_to my_profile_url, notice: I18n.t('home.changes_saved')
|
redirect_to my_profile_path, notice: I18n.t('home.changes_saved')
|
||||||
else
|
else
|
||||||
render :profile
|
render :profile
|
||||||
end
|
end
|
||||||
|
@ -64,7 +64,7 @@ class HomeController < ApplicationController
|
||||||
# cancel personal memberships direct from the myProfile-page
|
# cancel personal memberships direct from the myProfile-page
|
||||||
def cancel_membership
|
def cancel_membership
|
||||||
if params[:membership_id]
|
if params[:membership_id]
|
||||||
membership = @current_user.memberships.find!(params[:membership_id])
|
membership = @current_user.memberships.find(params[:membership_id])
|
||||||
else
|
else
|
||||||
membership = @current_user.memberships.find_by_group_id!(params[:group_id])
|
membership = @current_user.memberships.find_by_group_id!(params[:group_id])
|
||||||
end
|
end
|
||||||
|
|
12
spec/controllers/application_controller_spec.rb
Normal file
12
spec/controllers/application_controller_spec.rb
Normal 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
|
||||||
|
described_class.new.send(:store_controller)
|
||||||
|
expect(described_class.current).to be_instance_of described_class
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
340
spec/controllers/articles_controller_spec.rb
Normal file
340
spec/controllers/articles_controller_spec.rb
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ArticlesController, type: :controller do
|
||||||
|
let(:user) { create :user, :role_article_meta }
|
||||||
|
let(:article_category_a) { create :article_category, name: 'AAAA' }
|
||||||
|
let(:article_category_b) { create :article_category, name: 'BBBB' }
|
||||||
|
let(:article_category_c) { create :article_category, name: 'CCCC' }
|
||||||
|
let(:article_a) { create :article, name: 'AAAA', note: 'CCC', unit: '750 g', article_category: article_category_b, availability: false }
|
||||||
|
let(:article_b) { create :article, name: 'BBBB', note: 'AAA', unit: '500 g', article_category: article_category_a, availability: true }
|
||||||
|
let(:article_c) { create :article, name: 'CCCC', note: 'BBB', unit: '250 g', article_category: article_category_c, availability: true }
|
||||||
|
|
||||||
|
let(:supplier) { create :supplier, articles: [article_a, article_b, article_c] }
|
||||||
|
let(:order) { create :order }
|
||||||
|
let(:order2) { create :order }
|
||||||
|
|
||||||
|
def get_with_supplier(action, params: {}, xhr: false, format: nil)
|
||||||
|
params['supplier_id'] = supplier.id
|
||||||
|
get_with_defaults(action, params: params, xhr: xhr, format: format)
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_with_supplier(action, params: {}, xhr: false, format: nil)
|
||||||
|
params['supplier_id'] = supplier.id
|
||||||
|
post_with_defaults(action, params: params, xhr: xhr, format: format)
|
||||||
|
end
|
||||||
|
|
||||||
|
before { login user }
|
||||||
|
|
||||||
|
describe 'GET index' do
|
||||||
|
it 'assigns sorting on articles' do
|
||||||
|
sortings = [
|
||||||
|
['name', [article_a, article_b, article_c]],
|
||||||
|
['name_reverse', [article_c, article_b, article_a]],
|
||||||
|
['note', [article_b, article_c, article_a]],
|
||||||
|
['note_reverse', [article_a, article_c, article_b]],
|
||||||
|
['unit', [article_c, article_b, article_a]],
|
||||||
|
['unit_reverse', [article_a, article_b, article_c]],
|
||||||
|
['article_category', [article_b, article_a, article_c]],
|
||||||
|
['article_category_reverse', [article_c, article_a, article_b]],
|
||||||
|
['availability', [article_a, article_b, article_c]],
|
||||||
|
['availability_reverse', [article_b, article_c, article_a]]
|
||||||
|
]
|
||||||
|
sortings.each do |sorting|
|
||||||
|
get_with_supplier :index, params: { 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_with_supplier :index, format: :csv
|
||||||
|
expect(response.header['Content-Type']).to include('text/csv')
|
||||||
|
expect(response.body).to include(article_a.unit, article_b.unit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'new' do
|
||||||
|
it 'renders form for a new article' do
|
||||||
|
get_with_supplier :new, xhr: true
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'copy' do
|
||||||
|
it 'renders form with copy of an article' do
|
||||||
|
get_with_supplier :copy, params: { article_id: article_a.id }, xhr: true
|
||||||
|
expect(assigns(:article).attributes).to eq(article_a.dup.attributes)
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#create' do
|
||||||
|
it 'creates a new article' do
|
||||||
|
valid_attributes = article_a.attributes.except('id')
|
||||||
|
valid_attributes['name'] = 'ABAB'
|
||||||
|
get_with_supplier :create, params: { 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_with_supplier :create, params: { 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_with_supplier :edit, params: { id: article_a.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_with_supplier :edit_all, 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_with_supplier :update, params: { id: article_a.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 with empty name attribute' do
|
||||||
|
get_with_supplier :update, params: { id: article_a.id, article: { name: nil } }, xhr: true
|
||||||
|
expect(response).to render_template('articles/new')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update_all' do
|
||||||
|
it 'updates all articles' do
|
||||||
|
get_with_supplier :update_all, params: { articles: { "#{article_a.id}": attributes_for(:article), "#{article_b.id}": attributes_for(:article) } }
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails on updating all articles' do
|
||||||
|
get_with_supplier :update_all, params: { articles: { "#{article_a.id}": attributes_for(:article, name: 'ab') } }
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(response).to render_template('articles/edit_all')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update_selected' do
|
||||||
|
let(:order_article) { create :order_article, order: order, article: article_c }
|
||||||
|
|
||||||
|
before do
|
||||||
|
order_article
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates selected articles' do
|
||||||
|
get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id] }
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'destroys selected articles' do
|
||||||
|
get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'destroy' }
|
||||||
|
article_a.reload
|
||||||
|
article_b.reload
|
||||||
|
expect(article_a).to be_deleted
|
||||||
|
expect(article_b).to be_deleted
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets availability false on selected articles' do
|
||||||
|
get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'setNotAvailable' }
|
||||||
|
article_a.reload
|
||||||
|
article_b.reload
|
||||||
|
expect(article_a).not_to be_availability
|
||||||
|
expect(article_b).not_to be_availability
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets availability true on selected articles' do
|
||||||
|
get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'setAvailable' }
|
||||||
|
article_a.reload
|
||||||
|
article_b.reload
|
||||||
|
expect(article_a).to be_availability
|
||||||
|
expect(article_b).to be_availability
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails deletion if one article is in open order' do
|
||||||
|
get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_c.id], selected_action: 'destroy' }
|
||||||
|
article_a.reload
|
||||||
|
article_c.reload
|
||||||
|
expect(article_a).not_to be_deleted
|
||||||
|
expect(article_c).not_to be_deleted
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#parse_upload' do
|
||||||
|
let(:file) { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/files/upload_test.csv'), original_filename: 'upload_test.csv') }
|
||||||
|
|
||||||
|
it 'updates particles from spreadsheet' do
|
||||||
|
post_with_supplier :parse_upload, params: { articles: { file: file, outlist_absent: '1', convert_units: '1' } }
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'missing file not updates particles from spreadsheet' do
|
||||||
|
post_with_supplier :parse_upload, params: { articles: { file: nil, outlist_absent: '1', convert_units: '1' } }
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
expect(flash[:alert]).to match(I18n.t('errors.general_msg', msg: "undefined method `original_filename' for \"\":String").to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#sync' do
|
||||||
|
# TODO: double render error in controller
|
||||||
|
it 'throws double render error' do
|
||||||
|
expect do
|
||||||
|
post :sync, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }
|
||||||
|
end.to raise_error(AbstractController::DoubleRenderError)
|
||||||
|
end
|
||||||
|
|
||||||
|
xit 'updates particles from spreadsheet' do
|
||||||
|
post :sync, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: { '#{article_a.id}': attributes_for(:article), '#{article_b.id}': attributes_for(:article) } }
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
let(:order_article) { create :order_article, order: order, article: article_c }
|
||||||
|
|
||||||
|
before do
|
||||||
|
order_article
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not delete article if order open' do
|
||||||
|
get_with_supplier :destroy, params: { id: article_c.id }, xhr: true
|
||||||
|
expect(assigns(:article)).not_to be_deleted
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(response).to render_template('articles/destroy')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes article if order closed' do
|
||||||
|
get_with_supplier :destroy, params: { id: article_b.id }, xhr: true
|
||||||
|
expect(assigns(:article)).to be_deleted
|
||||||
|
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: article_c }
|
||||||
|
|
||||||
|
before do
|
||||||
|
order_article
|
||||||
|
article_a
|
||||||
|
article_b
|
||||||
|
article_c
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes articles' do
|
||||||
|
# TODO: double render error in controller
|
||||||
|
get_with_supplier :update_synchronized, params: { outlisted_articles: { article_a.id => article_a, article_b.id => article_b } }
|
||||||
|
article_a.reload
|
||||||
|
article_b.reload
|
||||||
|
expect(article_a).to be_deleted
|
||||||
|
expect(article_b).to be_deleted
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates articles' do
|
||||||
|
get_with_supplier :update_synchronized, params: { articles: { article_a.id => { name: 'NewNameA' }, article_b.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_with_supplier :update_synchronized, params: { articles: { article_a.id => { unit: '2000 g' }, article_b.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_with_supplier :update_synchronized, params: {
|
||||||
|
outlisted_articles: { article_a.id => article_a },
|
||||||
|
articles: {
|
||||||
|
article_a.id => { name: 'NewName' },
|
||||||
|
article_b.id => { name: 'AAAA' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error_array = [assigns(:updated_articles).first.errors.first, assigns(:updated_articles).last.errors.first]
|
||||||
|
expect(error_array).not_to be_any
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not delete articles in open order' do
|
||||||
|
get_with_supplier :update_synchronized, params: { outlisted_articles: { article_c.id => article_c } }
|
||||||
|
article_c.reload
|
||||||
|
expect(article_c).not_to be_deleted
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'assigns updated article_pairs on error' do
|
||||||
|
get_with_supplier :update_synchronized, params: {
|
||||||
|
articles: { article_a.id => { name: 'DDDD' } },
|
||||||
|
outlisted_articles: { article_c.id => article_c }
|
||||||
|
}
|
||||||
|
expect(assigns(:updated_article_pairs).first).to eq([article_a, { name: 'DDDD' }])
|
||||||
|
article_c.reload
|
||||||
|
expect(article_c).not_to be_deleted
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates articles in open order' do
|
||||||
|
get_with_supplier :update_synchronized, params: { articles: { article_c.id => { name: 'DDDD' } } }
|
||||||
|
article_c.reload
|
||||||
|
expect(article_c.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(:article_s) { create :article, name: 'SSSS', note: 'AAAA', unit: '250 g', article_category: article_category_a, availability: false }
|
||||||
|
|
||||||
|
let(:supplier_with_shared) { create :supplier, articles: [article_s], shared_supplier: shared_supplier }
|
||||||
|
|
||||||
|
it 'renders view with articles' do
|
||||||
|
get_with_defaults :shared, params: { supplier_id: supplier_with_shared.id, name_cont_all_joined: 'shared' }, xhr: true
|
||||||
|
expect(assigns(:supplier).shared_supplier.shared_articles).to be_any
|
||||||
|
expect(assigns(:articles)).to be_any
|
||||||
|
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_category_a
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fills form with article details' do
|
||||||
|
get_with_supplier :import, params: { article_category_id: article_category_b.id, direct: 'true', shared_article_id: shared_article.id }, xhr: true
|
||||||
|
expect(assigns(:article)).not_to be_nil
|
||||||
|
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_with_supplier :import, params: { article_category_id: article_category_b.id, shared_article_id: shared_article.id }, xhr: true
|
||||||
|
expect(assigns(:article)).not_to be_nil
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(response).to render_template(:new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
212
spec/controllers/concerns/auth_concern_spec.rb
Normal file
212
spec/controllers/concerns/auth_concern_spec.rb
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
def call_deny_access
|
||||||
|
deny_access
|
||||||
|
end
|
||||||
|
|
||||||
|
def call_current_user
|
||||||
|
current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
def call_login_and_redirect_to_return_to
|
||||||
|
user = User.find(params[:user_id])
|
||||||
|
login_and_redirect_to_return_to(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def call_login
|
||||||
|
user = User.find(params[:user_id])
|
||||||
|
login(user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# unit testing protected/private methods
|
||||||
|
describe 'protected/private methods' do
|
||||||
|
let(:user) { create :user }
|
||||||
|
let(:wrong_user) { create :user }
|
||||||
|
|
||||||
|
describe '#current_user' do
|
||||||
|
before do
|
||||||
|
login user
|
||||||
|
routes.draw { get 'call_current_user' => 'dummy_auth#call_current_user' }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with valid session' do
|
||||||
|
it 'returns current_user' do
|
||||||
|
get_with_defaults :call_current_user, params: { user_id: user.id }, format: JSON
|
||||||
|
expect(assigns(:current_user)).to eq user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with invalid session' do
|
||||||
|
it 'not returns current_user' do
|
||||||
|
session[:user_id] = nil
|
||||||
|
get_with_defaults :call_current_user, params: { user_id: nil }, format: JSON
|
||||||
|
expect(assigns(:current_user)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#deny_access' do
|
||||||
|
it 'redirects to root_url' do
|
||||||
|
login user
|
||||||
|
routes.draw { get 'deny_access' => 'dummy_auth#call_deny_access' }
|
||||||
|
get_with_defaults :call_deny_access
|
||||||
|
expect(response).to redirect_to(root_url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#login' do
|
||||||
|
before do
|
||||||
|
routes.draw { get 'call_login' => 'dummy_auth#call_login' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets user in session' do
|
||||||
|
login wrong_user
|
||||||
|
get_with_defaults :call_login, params: { user_id: user.id }, format: JSON
|
||||||
|
expect(session[:user_id]).to eq user.id
|
||||||
|
expect(session[:scope]).to eq FoodsoftConfig.scope
|
||||||
|
expect(session[:locale]).to eq user.locale
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#login_and_redirect_to_return_to' do
|
||||||
|
it 'redirects to already set target' do
|
||||||
|
login user
|
||||||
|
session[:return_to] = my_profile_url
|
||||||
|
routes.draw { get 'call_login_and_redirect_to_return_to' => 'dummy_auth#call_login_and_redirect_to_return_to' }
|
||||||
|
get_with_defaults :call_login_and_redirect_to_return_to, params: { user_id: user.id }
|
||||||
|
expect(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_with_defaults :authenticate_blank
|
||||||
|
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_with_defaults :authenticate_unknown_group
|
||||||
|
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_with_defaults :authenticate_pickups
|
||||||
|
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_with_defaults :authenticate_finance_or_orders
|
||||||
|
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_with_defaults :authenticate_finance_or_orders
|
||||||
|
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_with_defaults :try_authenticate_membership_or_admin, params: { 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 }
|
||||||
|
|
||||||
|
before { login user }
|
||||||
|
|
||||||
|
it 'authenticates token' do
|
||||||
|
routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
|
||||||
|
get_with_defaults :try_authenticate_or_token, params: { token: token_msg }
|
||||||
|
expect(response).not_to have_http_status(:redirect)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects on faulty token' do
|
||||||
|
routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
|
||||||
|
get_with_defaults :try_authenticate_or_token, params: { 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
|
||||||
|
routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
|
||||||
|
get_with_defaults :try_authenticate_or_token
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
211
spec/controllers/finance/balancing_controller_spec.rb
Normal file
211
spec/controllers/finance/balancing_controller_spec.rb
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
# 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_with_defaults :index
|
||||||
|
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_with_defaults :new, params: { 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_with_defaults :new, params: { 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_with_defaults :update_summary, params: { 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 }
|
||||||
|
|
||||||
|
it 'calls article update' do
|
||||||
|
get_with_defaults :new_on_order_article_update, params: { 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_with_defaults :new_on_order_article_create, params: { 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_with_defaults :edit_note, params: { 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_with_defaults :update_note, params: { 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_with_defaults :update_note, params: { 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_with_defaults :edit_transport, params: { 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_with_defaults :update_transport, params: { 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_with_defaults :update_transport, params: { 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_with_defaults :confirm, params: { 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_with_defaults :close, params: { id: order.id, type: fft.id }
|
||||||
|
expect(assigns(:order)).not_to be_closed
|
||||||
|
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_with_defaults :close, params: { id: order1.id, type: fft.id }
|
||||||
|
expect(assigns(:order)).to be_closed
|
||||||
|
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_with_defaults :close_direct, params: { id: order.id }
|
||||||
|
expect(assigns(:order)).to be_closed
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'closes order directly' do
|
||||||
|
get_with_defaults :close_direct, params: { id: order.id }
|
||||||
|
expect(assigns(:order)).to be_closed
|
||||||
|
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_with_defaults :close_all_direct_with_invoice
|
||||||
|
order.reload
|
||||||
|
expect(order).to be_closed
|
||||||
|
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_with_defaults :close_all_direct_with_invoice
|
||||||
|
order1.reload
|
||||||
|
expect(order1).not_to be_closed
|
||||||
|
expect(response).to have_http_status(:redirect)
|
||||||
|
expect(response).to redirect_to(finance_order_index_url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
30
spec/controllers/finance/base_controller_spec.rb
Normal file
30
spec/controllers/finance/base_controller_spec.rb
Normal 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_with_defaults :index
|
||||||
|
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
|
197
spec/controllers/home_controller_spec.rb
Normal file
197
spec/controllers/home_controller_spec.rb
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# 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_with_defaults :profile
|
||||||
|
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_with_defaults :index
|
||||||
|
|
||||||
|
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_with_defaults :profile
|
||||||
|
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_with_defaults :reference_calculator
|
||||||
|
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_with_defaults :reference_calculator
|
||||||
|
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_with_defaults :update_profile, params: { 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_with_defaults :update_profile, params: { 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_with_defaults :update_profile, params: { 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_with_defaults :ordergroup
|
||||||
|
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_with_defaults :ordergroup
|
||||||
|
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_with_defaults :ordergroup, params: { 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_with_defaults :cancel_membership
|
||||||
|
end.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
expect do
|
||||||
|
get_with_defaults :cancel_membership, params: { membership_id: 424242 }
|
||||||
|
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_with_defaults :cancel_membership, params: { 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
|
||||||
|
|
||||||
|
it 'removes user membership' do
|
||||||
|
membership = fin_user.memberships.first
|
||||||
|
get_with_defaults :cancel_membership, params: { membership_id: membership.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
|
67
spec/controllers/login_controller_spec.rb
Normal file
67
spec/controllers/login_controller_spec.rb
Normal 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_with_defaults :accept_invitation, params: { 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_with_defaults :accept_invitation, params: { 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_with_defaults :accept_invitation, params: { 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_with_defaults :accept_invitation, params: { 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_with_defaults :accept_invitation, params: { 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_with_defaults :accept_invitation, params: { 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
|
15
spec/factories/invite.rb
Normal file
15
spec/factories/invite.rb
Normal 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
|
8
spec/factories/order_article.rb
Normal file
8
spec/factories/order_article.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
require 'factory_bot'
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :order_article do
|
||||||
|
order { create :order }
|
||||||
|
article { create :article }
|
||||||
|
end
|
||||||
|
end
|
3
spec/fixtures/files/upload_test.csv
vendored
Normal file
3
spec/fixtures/files/upload_test.csv
vendored
Normal 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
|
|
3
spec/fixtures/upload_test.csv
vendored
Normal file
3
spec/fixtures/upload_test.csv
vendored
Normal 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
|
|
|
@ -21,6 +21,10 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# We use capybara with webkit, and need database_cleaner
|
# We use capybara with webkit, and need database_cleaner
|
||||||
|
config.before(:suite) do
|
||||||
|
DatabaseCleaner.clean_with(:truncation)
|
||||||
|
end
|
||||||
|
|
||||||
config.before(:each) do
|
config.before(:each) do
|
||||||
DatabaseCleaner.strategy = (RSpec.current_example.metadata[:js] ? :truncation : :transaction)
|
DatabaseCleaner.strategy = (RSpec.current_example.metadata[:js] ? :truncation : :transaction)
|
||||||
DatabaseCleaner.start
|
DatabaseCleaner.start
|
||||||
|
@ -51,8 +55,8 @@ RSpec.configure do |config|
|
||||||
# --seed 1234
|
# --seed 1234
|
||||||
config.order = "random"
|
config.order = "random"
|
||||||
|
|
||||||
|
config.include SpecTestHelper, type: :controller
|
||||||
config.include SessionHelper, type: :feature
|
config.include SessionHelper, type: :feature
|
||||||
|
|
||||||
# Automatically determine spec from directory structure, see:
|
# Automatically determine spec from directory structure, see:
|
||||||
# https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/directory-structure
|
# https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/directory-structure
|
||||||
config.infer_spec_type_from_file_location!
|
config.infer_spec_type_from_file_location!
|
||||||
|
|
28
spec/support/spec_test_helper.rb
Normal file
28
spec/support/spec_test_helper.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module SpecTestHelper
|
||||||
|
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
|
||||||
|
|
||||||
|
def get_with_defaults(action, params: {}, xhr: false, format: nil)
|
||||||
|
params['foodcoop'] = FoodsoftConfig[:default_scope]
|
||||||
|
get action, params: params, xhr: xhr, format: format
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_with_defaults(action, params: {}, xhr: false, format: nil)
|
||||||
|
params['foodcoop'] = FoodsoftConfig[:default_scope]
|
||||||
|
post action, params: params, xhr: xhr, format: format
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.include SpecTestHelper, :type => :controller
|
||||||
|
end
|
Loading…
Reference in a new issue