2018-10-15 16:47:14 +02:00
|
|
|
require 'spec_helper'
|
|
|
|
require 'apivore'
|
|
|
|
|
|
|
|
# we want to load a local file in YAML-format instead of a served JSON file
|
|
|
|
class SwaggerCheckerFile < Apivore::SwaggerChecker
|
|
|
|
def fetch_swagger!
|
|
|
|
YAML.load(File.read(swagger_path))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'API v1', type: :apivore, order: :defined do
|
|
|
|
include ApiHelper
|
|
|
|
|
|
|
|
subject { SwaggerCheckerFile.instance_for Rails.root.join('doc', 'swagger.v1.yml') }
|
|
|
|
|
2018-10-15 16:51:33 +02:00
|
|
|
context 'has valid paths' do
|
|
|
|
context 'user' do
|
2019-02-05 20:53:02 +01:00
|
|
|
let(:api_scopes) { ['user:read'] }
|
2018-10-15 16:51:33 +02:00
|
|
|
# create multiple users to make sure we're getting the authenticated user, not just any
|
|
|
|
let!(:other_user_1) { create :user }
|
|
|
|
let!(:user) { create :user }
|
|
|
|
let!(:other_user_2) { create :user }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/user', 200, api_auth) }
|
|
|
|
it { is_expected.to validate(:get, '/user', 401) }
|
|
|
|
|
2019-02-05 20:53:02 +01:00
|
|
|
it_handles_invalid_token_and_scope(:get, '/user')
|
2018-10-15 16:51:33 +02:00
|
|
|
end
|
|
|
|
|
2021-02-18 20:05:17 +01:00
|
|
|
context 'user/financial_overview' do
|
|
|
|
let(:api_scopes) { ['finance:user'] }
|
|
|
|
let!(:user) { create :user, :ordergroup }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_overview', 200, api_auth) }
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_overview', 401) }
|
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/user/financial_overview')
|
|
|
|
end
|
|
|
|
|
2018-10-13 16:27:24 +02:00
|
|
|
context 'user/financial_transactions' do
|
2020-07-25 16:18:59 +02:00
|
|
|
let(:api_scopes) { ['finance:user'] }
|
|
|
|
let(:other_user) { create :user, :ordergroup }
|
|
|
|
let!(:other_ft_1) { create :financial_transaction, ordergroup: other_user.ordergroup }
|
|
|
|
|
|
|
|
context 'without ordergroup' do
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions', 403, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions/{id}', 403, api_auth({ 'id' => other_ft_1.id })) }
|
2020-07-25 16:18:59 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with ordergroup' do
|
|
|
|
let(:user) { create :user, :ordergroup }
|
|
|
|
let!(:ft_1) { create :financial_transaction, ordergroup: user.ordergroup }
|
|
|
|
let!(:ft_2) { create :financial_transaction, ordergroup: user.ordergroup }
|
|
|
|
let!(:ft_3) { create :financial_transaction, ordergroup: user.ordergroup }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions/{id}', 200, api_auth({ 'id' => ft_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions/{id}', 404, api_auth({ 'id' => other_ft_1.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/user/financial_transactions/{id}', 404, api_auth({ 'id' => FinancialTransaction.last.id + 1 })) }
|
2020-07-25 16:18:59 +02:00
|
|
|
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { financial_transaction: { amount: 1, financial_transaction_type_id: ft_1.financial_transaction_type.id, note: 'note' } } } }
|
2021-02-18 12:37:22 +01:00
|
|
|
|
|
|
|
context 'without using self service' do
|
|
|
|
it { is_expected.to validate(:post, '/user/financial_transactions', 403, api_auth(create_params)) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with using self service' do
|
|
|
|
before { FoodsoftConfig[:use_self_service] = true }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/financial_transactions', 200, api_auth(create_params)) }
|
|
|
|
|
|
|
|
context 'with invalid financial transaction type' do
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { financial_transaction: { amount: 1, financial_transaction_type_id: -1, note: 'note' } } } }
|
2021-02-18 12:37:22 +01:00
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/financial_transactions', 404, api_auth(create_params)) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without note' do
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { financial_transaction: { amount: 1, financial_transaction_type_id: ft_1.financial_transaction_type.id } } } }
|
2021-02-18 12:37:22 +01:00
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/financial_transactions', 422, api_auth(create_params)) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without enough balance' do
|
|
|
|
before { FoodsoftConfig[:minimum_balance] = 1000 }
|
|
|
|
it { is_expected.to validate(:post, '/user/financial_transactions', 403, api_auth(create_params)) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-25 16:18:59 +02:00
|
|
|
it_handles_invalid_token_and_scope(:get, '/user/financial_transactions')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token_and_scope(:post, '/user/financial_transactions', -> { api_auth(create_params) })
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/user/financial_transactions/{id}', -> { api_auth('id' => ft_2.id) })
|
2020-07-25 16:18:59 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-13 16:27:24 +02:00
|
|
|
context 'user/group_order_articles' do
|
|
|
|
let(:api_scopes) { ['group_orders:user'] }
|
|
|
|
let(:order) { create(:order, article_count: 2) }
|
|
|
|
|
|
|
|
let(:user_2) { create :user, :ordergroup }
|
|
|
|
let(:group_order_2) { create(:group_order, order: order, ordergroup: user_2.ordergroup) }
|
|
|
|
let!(:goa_2) { create :group_order_article, order_article: order.order_articles[0], group_order: group_order_2 }
|
|
|
|
before { group_order_2.update_price!; user_2.ordergroup.update_stats! }
|
|
|
|
|
|
|
|
context 'without ordergroup' do
|
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles', 403, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles/{id}', 403, api_auth({ 'id' => goa_2.id })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with ordergroup' do
|
|
|
|
let(:user) { create :user, :ordergroup }
|
|
|
|
let(:group_order) { create(:group_order, order: order, ordergroup: user.ordergroup) }
|
|
|
|
let!(:goa) { create :group_order_article, order_article: order.order_articles[0], group_order: group_order }
|
|
|
|
before { group_order.update_price!; user.ordergroup.update_stats! }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles/{id}', 200, api_auth({ 'id' => goa.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles/{id}', 404, api_auth({ 'id' => goa_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/user/group_order_articles/{id}', 404, api_auth({ 'id' => GroupOrderArticle.last.id + 1 })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { group_order_article: { order_article_id: order.order_articles[1].id, quantity: 1 } } } }
|
|
|
|
let(:update_params) { { 'id' => goa.id, '_data' => { group_order_article: { quantity: goa.quantity + 1, tolerance: 0 } } } }
|
2018-10-13 16:27:24 +02:00
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 200, api_auth(create_params)) }
|
|
|
|
it { is_expected.to validate(:patch, '/user/group_order_articles/{id}', 200, api_auth(update_params)) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:delete, '/user/group_order_articles/{id}', 200, api_auth({ 'id' => goa.id })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
|
|
|
|
context 'with an existing group_order_article' do
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { group_order_article: { order_article_id: order.order_articles[0].id, quantity: 1 } } } }
|
2018-10-13 16:27:24 +02:00
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 422, api_auth(create_params)) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with invalid parameter values' do
|
2021-03-01 15:27:26 +01:00
|
|
|
let(:create_params) { { '_data' => { group_order_article: { order_article_id: order.order_articles[0].id, quantity: -1 } } } }
|
|
|
|
let(:update_params) { { 'id' => goa.id, '_data' => { group_order_article: { quantity: -1, tolerance: 0 } } } }
|
2018-10-13 16:27:24 +02:00
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 422, api_auth(create_params)) }
|
|
|
|
it { is_expected.to validate(:patch, '/user/group_order_articles/{id}', 422, api_auth(update_params)) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with a closed order' do
|
|
|
|
let(:order) { create(:order, article_count: 2, state: :finished) }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 404, api_auth(create_params)) }
|
|
|
|
it { is_expected.to validate(:patch, '/user/group_order_articles/{id}', 404, api_auth(update_params)) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:delete, '/user/group_order_articles/{id}', 404, api_auth({ 'id' => goa.id })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without enough balance' do
|
|
|
|
before { FoodsoftConfig[:minimum_balance] = 1000 }
|
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 403, api_auth(create_params)) }
|
|
|
|
it { is_expected.to validate(:patch, '/user/group_order_articles/{id}', 403, api_auth(update_params)) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:delete, '/user/group_order_articles/{id}', 200, api_auth({ 'id' => goa.id })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without enough apple points' do
|
2021-03-01 15:27:26 +01:00
|
|
|
before { allow_any_instance_of(Ordergroup).to receive(:not_enough_apples?).and_return(true) }
|
2018-10-13 16:27:24 +02:00
|
|
|
it { is_expected.to validate(:post, '/user/group_order_articles', 403, api_auth(create_params)) }
|
|
|
|
it { is_expected.to validate(:patch, '/user/group_order_articles/{id}', 403, api_auth(update_params)) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:delete, '/user/group_order_articles/{id}', 200, api_auth({ 'id' => goa.id })) }
|
2018-10-13 16:27:24 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/user/group_order_articles')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token_and_scope(:post, '/user/group_order_articles', -> { api_auth(create_params) })
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/user/group_order_articles/{id}', -> { api_auth({ 'id' => goa.id }) })
|
|
|
|
it_handles_invalid_token_and_scope(:patch, '/user/group_order_articles/{id}', -> { api_auth(update_params) })
|
|
|
|
it_handles_invalid_token_and_scope(:delete, '/user/group_order_articles/{id}', -> { api_auth({ 'id' => goa.id }) })
|
2018-10-13 16:27:24 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-15 16:51:33 +02:00
|
|
|
context 'config' do
|
2019-02-05 20:53:02 +01:00
|
|
|
let(:api_scopes) { ['config:user'] }
|
|
|
|
|
2018-10-15 16:51:33 +02:00
|
|
|
it { is_expected.to validate(:get, '/config', 200, api_auth) }
|
|
|
|
it { is_expected.to validate(:get, '/config', 401) }
|
2019-02-05 20:53:02 +01:00
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/config')
|
2018-10-15 16:51:33 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'navigation' do
|
|
|
|
it { is_expected.to validate(:get, '/navigation', 200, api_auth) }
|
|
|
|
it { is_expected.to validate(:get, '/navigation', 401) }
|
2019-02-05 20:53:02 +01:00
|
|
|
|
|
|
|
it_handles_invalid_token(:get, '/navigation')
|
2018-10-15 16:51:33 +02:00
|
|
|
end
|
2020-07-25 16:18:59 +02:00
|
|
|
|
|
|
|
context 'financial_transactions' do
|
|
|
|
let(:api_scopes) { ['finance:read'] }
|
|
|
|
let(:user) { create(:user, :role_finance) }
|
|
|
|
let(:other_user) { create :user, :ordergroup }
|
|
|
|
let!(:ft_1) { create :financial_transaction, ordergroup: other_user.ordergroup }
|
|
|
|
let!(:ft_2) { create :financial_transaction, ordergroup: other_user.ordergroup }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/financial_transactions', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/financial_transactions/{id}', 200, api_auth({ 'id' => ft_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/financial_transactions/{id}', 404, api_auth({ 'id' => FinancialTransaction.last.id + 1 })) }
|
2020-07-25 16:18:59 +02:00
|
|
|
|
|
|
|
context 'without role_finance' do
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
it { is_expected.to validate(:get, '/financial_transactions', 403, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/financial_transactions/{id}', 403, api_auth({ 'id' => ft_2.id })) }
|
2020-07-25 16:18:59 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/financial_transactions')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token_and_scope(:get, '/financial_transactions/{id}', -> { api_auth({ 'id' => ft_2.id }) })
|
2020-07-25 16:18:59 +02:00
|
|
|
end
|
2021-02-08 01:08:37 +01:00
|
|
|
|
|
|
|
context 'financial_transaction_classes' do
|
|
|
|
let!(:cla_1) { create :financial_transaction_class }
|
|
|
|
let!(:cla_2) { create :financial_transaction_class }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_classes', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_classes/{id}', 200, api_auth({ 'id' => cla_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_classes/{id}', 404, api_auth({ 'id' => cla_2.id + 1 })) }
|
2021-02-08 01:08:37 +01:00
|
|
|
|
|
|
|
it_handles_invalid_token(:get, '/financial_transaction_classes')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token(:get, '/financial_transaction_classes/{id}', -> { api_auth({ 'id' => cla_1.id }) })
|
2021-02-08 01:08:37 +01:00
|
|
|
end
|
2021-02-08 01:08:52 +01:00
|
|
|
|
|
|
|
context 'financial_transaction_types' do
|
|
|
|
let!(:tpy_1) { create :financial_transaction_type }
|
|
|
|
let!(:tpy_2) { create :financial_transaction_type }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_types', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_types/{id}', 200, api_auth({ 'id' => tpy_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/financial_transaction_types/{id}', 404, api_auth({ 'id' => tpy_2.id + 1 })) }
|
2021-02-08 01:08:52 +01:00
|
|
|
|
|
|
|
it_handles_invalid_token(:get, '/financial_transaction_types')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token(:get, '/financial_transaction_types/{id}', -> { api_auth({ 'id' => tpy_1.id }) })
|
2021-02-08 01:08:52 +01:00
|
|
|
end
|
2018-10-13 16:16:44 +02:00
|
|
|
|
|
|
|
context 'orders' do
|
|
|
|
let(:api_scopes) { ['orders:read'] }
|
|
|
|
let!(:order) { create :order }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/orders', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/orders/{id}', 200, api_auth({ 'id' => order.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/orders/{id}', 404, api_auth({ 'id' => Order.last.id + 1 })) }
|
2018-10-13 16:16:44 +02:00
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/orders')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token_and_scope(:get, '/orders/{id}', -> { api_auth({ 'id' => order.id }) })
|
2018-10-13 16:16:44 +02:00
|
|
|
end
|
2018-10-13 16:21:37 +02:00
|
|
|
|
|
|
|
context 'order_articles' do
|
|
|
|
let(:api_scopes) { ['orders:read'] }
|
|
|
|
let!(:order_article) { create(:order, article_count: 1).order_articles.first }
|
|
|
|
let!(:stock_article) { create(:stock_article) }
|
|
|
|
let!(:stock_order_article) { create(:stock_order, article_ids: [stock_article.id]).order_articles.first }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/order_articles', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/order_articles/{id}', 200, api_auth({ 'id' => order_article.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/order_articles/{id}', 200, api_auth({ 'id' => stock_order_article.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/order_articles/{id}', 404, api_auth({ 'id' => Article.last.id + 1 })) }
|
2018-10-13 16:21:37 +02:00
|
|
|
|
|
|
|
it_handles_invalid_token_and_scope(:get, '/order_articles')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token_and_scope(:get, '/order_articles/{id}', -> { api_auth({ 'id' => order_article.id }) })
|
2018-10-13 16:21:37 +02:00
|
|
|
end
|
2018-10-13 16:29:36 +02:00
|
|
|
|
|
|
|
context 'article_categories' do
|
|
|
|
let!(:cat_1) { create :article_category }
|
|
|
|
let!(:cat_2) { create :article_category }
|
|
|
|
|
|
|
|
it { is_expected.to validate(:get, '/article_categories', 200, api_auth) }
|
2021-03-01 15:27:26 +01:00
|
|
|
it { is_expected.to validate(:get, '/article_categories/{id}', 200, api_auth({ 'id' => cat_2.id })) }
|
|
|
|
it { is_expected.to validate(:get, '/article_categories/{id}', 404, api_auth({ 'id' => cat_2.id + 1 })) }
|
2018-10-13 16:29:36 +02:00
|
|
|
|
|
|
|
it_handles_invalid_token(:get, '/article_categories')
|
2021-03-01 15:27:26 +01:00
|
|
|
it_handles_invalid_token(:get, '/article_categories/{id}', -> { api_auth({ 'id' => cat_1.id }) })
|
2018-10-13 16:29:36 +02:00
|
|
|
end
|
2018-10-15 16:51:33 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
# needs to be last context so it is always run at the end
|
|
|
|
context 'and finally' do
|
|
|
|
it 'tests all documented routes' do
|
|
|
|
is_expected.to validate_all_paths
|
|
|
|
end
|
2018-10-15 16:47:14 +02:00
|
|
|
end
|
|
|
|
end
|