require 'support/crud_controller_test_helper' RSpec.configure do |c| c.before failing: true do allow_any_instance_of(model_class).to receive(:save).and_return(false) allow_any_instance_of(model_class).to receive(:destroy).and_return(false) end end # A set of examples to include into the tests for your crud controller # subclasses. Simply #let :test_entry, :new_entry_attrs and :edit_entry_attrs # to test the basic crud functionality. # If single examples do not match with you implementation, you may skip # them by passing a skip parameter with context arrays: # include_examples 'crud controller', # skip: [%w(index html sort) %w(destroy json)] shared_examples 'crud controller' do |options| include CrudControllerTestHelper render_views subject { response } let(:model_class) { controller.send(:model_class) } let(:model_identifier) { controller.model_identifier } let(:test_params) { scope_params } let(:sort_column) { model_class.column_names.first } let(:ivar_name) { controller.send(:ivar_name, model_class) } let(:entry) { ivar(ivar_name) } let(:entries) { ivar(ivar_name.pluralize) } let(:search_value) do field = controller.search_columns.first val = test_entry[field].to_s val[0..((val.size + 1) / 2)] end before do m = RSpec.current_example.metadata if m[:perform_request] != false && m[:action] && m[:method] perform_combined_request end end describe_action :get, :index, unless: skip?(options, 'index') do context '.html', format: :html, unless: skip?(options, %w[index html]) do context 'plain', unless: skip?(options, %w[index html plain]), combine: 'ihp' do it_is_expected_to_respond end context 'search', if: described_class.search_columns.present?, unless: skip?(options, %w[index html search]), combine: 'ihse' do let(:params) { { q: search_value } } it_is_expected_to_respond context 'entries' do subject { entries } it { is_expected.to include(test_entry) } end end context 'sort', unless: skip?(options, %w[index html sort]) do context 'ascending', unless: skip?(options, %w[index html sort ascending]), combine: 'ihso' do let(:params) { { sort: sort_column, sort_dir: 'asc' } } it_is_expected_to_respond it 'has sorted entries' do sorted = entries.sort_by(&sort_column.to_sym) expect(entries).to eq(sorted) end end context 'descending', unless: skip?(options, %w[index html sort descending]), combine: 'ihsd' do let(:params) { { sort: sort_column, sort_dir: 'desc' } } it_is_expected_to_respond it 'has sorted entries' do sorted = entries.sort_by(&sort_column.to_sym) expect(entries).to eq(sorted.reverse) end end end end context '.json', format: :json, unless: skip?(options, %w[index json]), combine: 'ij' do it_is_expected_to_respond it { expect(response.body).to start_with('[{') } end end describe_action :get, :show, id: true, unless: skip?(options, 'show') do context '.html', format: :html, unless: skip?(options, %w[show html]) do context 'plain', unless: skip?(options, %w[show html plain]), combine: 'sh' do it_is_expected_to_respond end context 'with non-existing id', unless: skip?(options, %w[show html with_non_existing_id]) do let(:params) { { id: 9999 } } it 'raises RecordNotFound', perform_request: false do expect { perform_request } .to raise_error(ActiveRecord::RecordNotFound) end end end context '.json', format: :json, unless: skip?(options, %w[show json]), combine: 'sj' do it_is_expected_to_respond it_is_expected_to_render_json end end describe_action :get, :new, unless: skip?(options, %w[new]) do context 'plain', unless: skip?(options, %w[new plain]), combine: 'new' do it_is_expected_to_respond it_is_expected_to_persist_entry(false) end context 'with params', unless: skip?(options, %w[new with_params]) do let(:params) { { model_identifier => new_entry_attrs } } it_is_expected_to_set_attrs(:new) end end describe_action :post, :create, unless: skip?(options, %w[create]) do let(:params) { { model_identifier => new_entry_attrs } } it 'adds entry to database', perform_request: false do expect { perform_request }.to change { model_class.count }.by(1) end context 'html', format: :html, unless: skip?(options, %w[create html]) do it_is_expected_to_persist_entry # cannot combine this context 'with valid params', unless: skip?(options, %w[create html valid]), combine: 'chv' do it_is_expected_to_redirect_to_show it_is_expected_to_set_attrs(:new) it_is_expected_to_have_flash(:notice) end context 'with invalid params', failing: true, unless: skip?(options, %w[create html invalid]), combine: 'chi' do it_is_expected_to_persist_entry(false) it_is_expected_to_set_attrs(:new) it_is_expected_to_not_have_flash(:notice) end end context 'json', format: :json, unless: skip?(options, %w[create json]) do it_is_expected_to_persist_entry # cannot combine this context 'with valid params', unless: skip?(options, %w[create json valid]), combine: 'cjv' do it_is_expected_to_respond(201) it_is_expected_to_set_attrs(:new) it_is_expected_to_render_json end context 'with invalid params', failing: true, unless: skip?(options, %w[create json invalid]), combine: 'cji' do it_is_expected_to_respond(422) it_is_expected_to_set_attrs(:new) it_is_expected_to_render_json it_is_expected_to_persist_entry(false) end end end describe_action :get, :edit, id: true, unless: skip?(options, %w[edit]), combine: 'edit' do it_is_expected_to_respond end describe_action :put, :update, id: true, unless: skip?(options, %w[update]) do let(:params) { { model_identifier => edit_entry_attrs } } it 'updates entry in database', perform_request: false do expect { perform_request }.to change { model_class.count }.by(0) end context '.html', format: :html, unless: skip?(options, %w[update html]) do context 'with valid params', unless: skip?(options, %w[update html valid]), combine: 'uhv' do it_is_expected_to_set_attrs(:edit) it_is_expected_to_redirect_to_show it_is_expected_to_persist_entry it_is_expected_to_have_flash(:notice) end context 'with invalid params', failing: true, unless: skip?(options, %w[update html invalid]), combine: 'uhi' do it_is_expected_to_set_attrs(:edit) it_is_expected_to_not_have_flash(:notice) end end context '.json', format: :json, unless: skip?(options, %w[update json]) do context 'with valid params', unless: skip?(options, %w[update json valid]), combine: 'ujv' do it_is_expected_to_respond(200) it_is_expected_to_set_attrs(:edit) it_is_expected_to_render_json it_is_expected_to_persist_entry end context 'with invalid params', failing: true, unless: skip?(options, %w[update json invalid]), combine: 'uji' do it_is_expected_to_respond(422) it_is_expected_to_set_attrs(:edit) it_is_expected_to_render_json end end end describe_action :delete, :destroy, id: true, unless: skip?(options, %w[destroy]) do it 'removes entry from database', perform_request: false do expect { perform_request }.to change { model_class.count }.by(-1) end context '.html', format: :html, unless: skip?(options, %w[destroy html]) do context 'successfull', combine: 'dhs' do it_is_expected_to_redirect_to_index it_is_expected_to_have_flash(:notice) end context 'with failure', failing: true, combine: 'dhf' do it_is_expected_to_redirect_to_index it_is_expected_to_have_flash(:alert) end end context '.json', format: :json, unless: skip?(options, %w[destroy json]) do context 'successfull', combine: 'djs' do it_is_expected_to_respond(204) it { expect(response.body).to be_blank } end context 'with failure', failing: true, combine: 'djf' do it_is_expected_to_respond(422) it_is_expected_to_render_json end end end end