diff --git a/spec/app_config.yml b/spec/app_config.yml index 2e146be9..861bded3 100644 --- a/spec/app_config.yml +++ b/spec/app_config.yml @@ -7,6 +7,7 @@ default: &defaults multi_coop_install: false default_scope: 'f' + tax_default: 0 name: FC Minimal diff --git a/spec/controllers/articles_controller_spec.rb b/spec/controllers/articles_controller_spec.rb index 79d8f0ac..2fdee31a 100644 --- a/spec/controllers/articles_controller_spec.rb +++ b/spec/controllers/articles_controller_spec.rb @@ -4,16 +4,19 @@ 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 } + let(:order_article) { create :order_article, order: order, article: articleC } before { login user } describe 'GET index' do - 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(:supplier) { create :supplier, articles: [articleA, articleB] } - it 'assigns sorting on articles' do sortings = [ ['name', [articleA, articleB]], @@ -33,5 +36,264 @@ describe ArticlesController, type: :controller do 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 an 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 + 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?? + # #":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 + 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 + 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, q: { name_cont_all: "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 end diff --git a/spec/factories/order_article.rb b/spec/factories/order_article.rb new file mode 100644 index 00000000..99ca8701 --- /dev/null +++ b/spec/factories/order_article.rb @@ -0,0 +1,8 @@ +require 'factory_bot' + +FactoryBot.define do + factory :order_article do + order { create :order } + article { create :article } + end +end diff --git a/spec/fixtures/files/upload_test.csv b/spec/fixtures/files/upload_test.csv new file mode 100644 index 00000000..ac2f59b0 --- /dev/null +++ b/spec/fixtures/files/upload_test.csv @@ -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 diff --git a/spec/fixtures/upload_test.csv b/spec/fixtures/upload_test.csv new file mode 100644 index 00000000..ac2f59b0 --- /dev/null +++ b/spec/fixtures/upload_test.csv @@ -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