From 508df91cb9509bac3ddad9ea5aa493476426a55e Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Fri, 18 Oct 2019 14:30:18 +0200 Subject: [PATCH 1/7] Display only one Back button for Policy simulation Issue: https://github.com/ManageIQ/manageiq-ui-classic/issues/6263 (cherry picked from commit 42745084282dc51e8e76a1b773ea8ce1cedae276) --- app/controllers/vm_common.rb | 4 ++ spec/controllers/vm_common_spec.rb | 75 +++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/app/controllers/vm_common.rb b/app/controllers/vm_common.rb index 1866f0f9f14..62bb12f19ec 100644 --- a/app/controllers/vm_common.rb +++ b/app/controllers/vm_common.rb @@ -460,6 +460,7 @@ def policies :options => @policy_options) @edit = session[:edit] if session[:edit] if @edit && @edit[:explorer] + @sb[:explorer] = true if session[:policies].empty? render_flash(_("No policies were selected for Policy Simulation."), :error) return @@ -467,11 +468,13 @@ def policies @in_a_form = true replace_right_cell(:action => 'policy_sim', :refresh_breadcrumbs => false) else + @sb[:explorer] = nil render :template => 'vm/show' end end def policy_show_options + @explorer = @sb[:explorer] if params[:passed] == "null" || params[:passed] == "" @policy_options[:passed] = false @policy_options[:failed] = true @@ -495,6 +498,7 @@ def policy_show_options # Show/Unshow out of scope items def policy_options + @explorer = @sb[:explorer] @vm = @record = identify_record(params[:id], VmOrTemplate) @policy_options ||= {} @policy_options[:out_of_scope] = (params[:out_of_scope] == "1") diff --git a/spec/controllers/vm_common_spec.rb b/spec/controllers/vm_common_spec.rb index 357e50fd064..da62e8d9a55 100644 --- a/spec/controllers/vm_common_spec.rb +++ b/spec/controllers/vm_common_spec.rb @@ -46,7 +46,7 @@ end end - describe '#reload ' do + describe '#reload' do before do login_as FactoryBot.create(:user_with_group, :role => "operator") allow(controller).to receive(:tree_select).and_return(nil) @@ -335,6 +335,79 @@ end end + describe '#policy_show_options' do + let(:vm) { FactoryBot.create(:vm_vmware) } + + before do + allow(controller).to receive(:render) + controller.instance_variable_set(:@sb, {}) + controller.params = {:id => vm.id} + end + + it 'sets @explorer to nil' do + controller.send(:policy_show_options) + expect(controller.instance_variable_get(:@explorer)).to be_nil + end + + context 'explorer screen' do + before { controller.instance_variable_set(:@sb, :explorer => true) } + + it 'sets @explorer to true' do + controller.send(:policy_show_options) + expect(controller.instance_variable_get(:@explorer)).to be(true) + end + end + end + + describe '#policies' do + let(:vm) { FactoryBot.create(:vm_vmware) } + + before do + allow(controller).to receive(:render) + allow(controller).to receive(:session).and_return(:policies => {}) + controller.instance_variable_set(:@sb, {}) + controller.params = {:id => vm.id} + end + + it 'sets @sb[:explorer] to false' do + controller.send(:policies) + expect(controller.instance_variable_get(:@sb)[:explorer]).to be_nil + end + + context 'explorer screen' do + before { allow(controller).to receive(:session).and_return(:policies => {}, :edit => {:explorer => true}) } + + it 'sets @sb[:explorer] to true' do + controller.send(:policies) + expect(controller.instance_variable_get(:@sb)[:explorer]).to be(true) + end + end + end + + describe '#policy_options' do + let(:vm) { FactoryBot.create(:vm_vmware) } + + before do + allow(controller).to receive(:render) + controller.instance_variable_set(:@sb, {}) + controller.params = {:id => vm.id} + end + + it 'sets @explorer to false' do + controller.send(:policy_options) + expect(controller.instance_variable_get(:@explorer)).to be_nil + end + + context 'explorer screen' do + before { controller.instance_variable_set(:@sb, :explorer => true) } + + it 'sets @explorer to false' do + controller.send(:policy_options) + expect(controller.instance_variable_get(:@explorer)).to be(true) + end + end + end + include_examples '#download_summary_pdf', :vm_cloud include_examples '#download_summary_pdf', :vm_infra end From 49b1c759758833ddaae4ababd7f7da54599e86cb Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Mon, 23 Sep 2019 16:25:33 +0200 Subject: [PATCH 2/7] Get proper record class for items displayed through various controllers Issue: https://github.com/ManageIQ/manageiq-ui-classic/issues/5924 Get proper record class for items displayed through Storage Relationships, also for items displayed through Cluster's Relationships, items in Services Workloads, VMs, Instances, Images displayed through various controllers. (cherry picked from commit 5269ad8026107db655a8e63c50c8d752ef326f45) --- .../cloud_object_store_container_controller.rb | 4 ++++ .../cloud_object_store_object_controller.rb | 4 ++++ app/controllers/ems_cluster_controller.rb | 4 ++++ app/controllers/ems_infra_controller.rb | 13 +++++++++++++ app/controllers/ems_storage_controller.rb | 4 ++++ app/controllers/host_controller.rb | 11 +++++++++++ app/controllers/miq_template_controller.rb | 4 ++++ app/controllers/orchestration_stack_controller.rb | 4 ++++ app/controllers/resource_pool_controller.rb | 4 ++++ app/controllers/service_controller.rb | 4 ++++ app/controllers/storage_controller.rb | 4 ++++ 11 files changed, 60 insertions(+) diff --git a/app/controllers/cloud_object_store_container_controller.rb b/app/controllers/cloud_object_store_container_controller.rb index e90d6d017df..6da9f1267ab 100644 --- a/app/controllers/cloud_object_store_container_controller.rb +++ b/app/controllers/cloud_object_store_container_controller.rb @@ -119,6 +119,10 @@ def form_params_create private + def record_class + params[:pressed].starts_with?('cloud_object_store_object') ? CloudObjectStoreObject : CloudObjectStoreContainer + end + def retrieve_provider_regions managers = ManageIQ::Providers::CloudManager.supported_subclasses.select(&:supports_regions?) managers.each_with_object({}) do |manager, provider_regions| diff --git a/app/controllers/cloud_object_store_object_controller.rb b/app/controllers/cloud_object_store_object_controller.rb index ea3c4340b34..01ae8d3043d 100644 --- a/app/controllers/cloud_object_store_object_controller.rb +++ b/app/controllers/cloud_object_store_object_controller.rb @@ -29,6 +29,10 @@ def title private + def record_class + CloudObjectStoreObject + end + def textual_group_list [%i[properties relationships], %i[tags]] end diff --git a/app/controllers/ems_cluster_controller.rb b/app/controllers/ems_cluster_controller.rb index 5855de1cdf1..9e29b5db7e9 100644 --- a/app/controllers/ems_cluster_controller.rb +++ b/app/controllers/ems_cluster_controller.rb @@ -95,6 +95,10 @@ def button private + def record_class + %w[all_vms vms].include?(params[:display]) || params[:pressed].starts_with?('miq_template') ? VmOrTemplate : EmsCluster + end + def textual_group_list [ %i[relationships], diff --git a/app/controllers/ems_infra_controller.rb b/app/controllers/ems_infra_controller.rb index 6678c015a09..092f1154cdf 100644 --- a/app/controllers/ems_infra_controller.rb +++ b/app/controllers/ems_infra_controller.rb @@ -224,6 +224,19 @@ def ems_infra_form_fields private + def record_class + case params[:pressed] + when /^ems_cluster/ + EmsCluster + when /^orchestration_stack/ + OrchestrationStack + when /^storage/ + Storage + else + VmOrTemplate + end + end + ############################ # Special EmsCloud link builder for restful routes def show_link(ems, options = {}) diff --git a/app/controllers/ems_storage_controller.rb b/app/controllers/ems_storage_controller.rb index 1b2f203524e..cc75b543ad6 100644 --- a/app/controllers/ems_storage_controller.rb +++ b/app/controllers/ems_storage_controller.rb @@ -73,6 +73,10 @@ def breadcrumbs_options private + def record_class + params[:pressed].starts_with?('cloud_object_store_object') ? CloudObjectStoreObject : CloudObjectStoreContainer + end + def textual_group_list [ %i[properties status], diff --git a/app/controllers/host_controller.rb b/app/controllers/host_controller.rb index 81449c76050..94c9059ea98 100644 --- a/app/controllers/host_controller.rb +++ b/app/controllers/host_controller.rb @@ -429,6 +429,17 @@ def host_form_fields private + def record_class + case params[:display] || @display + when 'storages' + Storage + when 'vms', 'miq_templates' + VmOrTemplate + else + Host + end + end + def textual_group_list [ %i[properties relationships], diff --git a/app/controllers/miq_template_controller.rb b/app/controllers/miq_template_controller.rb index 40a4559452c..0bc43a63bb8 100644 --- a/app/controllers/miq_template_controller.rb +++ b/app/controllers/miq_template_controller.rb @@ -18,6 +18,10 @@ def index private + def record_class + MiqTemplate + end + def get_session_data @title = _("Templates") @layout = session[:miq_template_type] ? session[:miq_template_type] : "miq_template" diff --git a/app/controllers/orchestration_stack_controller.rb b/app/controllers/orchestration_stack_controller.rb index 040299b6f80..7945683b03f 100644 --- a/app/controllers/orchestration_stack_controller.rb +++ b/app/controllers/orchestration_stack_controller.rb @@ -146,6 +146,10 @@ def stacks_ot_copy private + def record_class + params[:display] == 'instances' ? VmOrTemplate : OrchestrationStack + end + def textual_group_list [%i[properties lifecycle relationships], %i[tags]] end diff --git a/app/controllers/resource_pool_controller.rb b/app/controllers/resource_pool_controller.rb index c5cfe8b381c..ba1359609a7 100644 --- a/app/controllers/resource_pool_controller.rb +++ b/app/controllers/resource_pool_controller.rb @@ -64,6 +64,10 @@ def button private + def record_class + %w[all_vms vms].include?(params[:display]) ? VmOrTemplate : ResourcePool + end + def textual_group_list [%i[properties relationships], %i[configuration smart_management]] end diff --git a/app/controllers/service_controller.rb b/app/controllers/service_controller.rb index d19b4a90650..fa1d135e5ef 100644 --- a/app/controllers/service_controller.rb +++ b/app/controllers/service_controller.rb @@ -204,6 +204,10 @@ def display_generic_objects private + def record_class + Service + end + def sanitize_output(stdout) htm = stdout.gsub('"', '\"') diff --git a/app/controllers/storage_controller.rb b/app/controllers/storage_controller.rb index 6e53d28ee48..f8d87def430 100644 --- a/app/controllers/storage_controller.rb +++ b/app/controllers/storage_controller.rb @@ -471,6 +471,10 @@ def storage_scan private + def record_class + %w[all_vms vms].include?(params[:display]) ? VmOrTemplate : Storage + end + def session_reset if @record session[:edit] = @edit = nil From aff54eeeb506b3734ab6d023255750651572f978 Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Tue, 15 Oct 2019 10:23:33 +0200 Subject: [PATCH 3/7] Refactor get_rec_cls, add default record_class in the CiProcessing (cherry picked from commit 673399bbace5a3e6f28a2b5cc869183bf065f2d3) --- .../application_controller/ci_processing.rb | 31 +++---------------- app/controllers/vm_common.rb | 2 +- spec/controllers/vm_common_spec.rb | 11 +++++++ 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/app/controllers/application_controller/ci_processing.rb b/app/controllers/application_controller/ci_processing.rb index 45b18ad5bb7..47a5d85eca4 100644 --- a/app/controllers/application_controller/ci_processing.rb +++ b/app/controllers/application_controller/ci_processing.rb @@ -222,7 +222,7 @@ def breadcrumb_name(_model) def process_cloud_object_storage_buttons(pressed) assert_privileges(pressed) - klass = get_rec_cls + klass = record_class task = pressed.sub("#{klass.name.underscore.to_sym}_", "") return tag(klass) if task == "tag" @@ -247,33 +247,12 @@ def cloud_object_store_button_operation(klass, task) process_objects(items.ids.sort, method, display_name) end - def get_rec_cls - # FIXME: the specs for ci_processing rely on setting (and testing) request.parameters['controller']. - # That is wrong and needs to be fixed. - case request.parameters["controller"] || controller_name - when "miq_template" - MiqTemplate - when "orchestration_stack" - params[:display] == "instances" ? VmOrTemplate : OrchestrationStack - when "service" - Service - when "cloud_object_store_container" - params[:pressed].starts_with?("cloud_object_store_object") ? CloudObjectStoreObject : CloudObjectStoreContainer - when "cloud_object_store_object" - CloudObjectStoreObject - when "ems_storage" - params[:pressed].starts_with?("cloud_object_store_object") ? CloudObjectStoreObject : CloudObjectStoreContainer - when "ems_cluster" - %w[all_vms vms].include?(params[:display]) || params[:pressed].starts_with?('miq_template') ? VmOrTemplate : EmsCluster - when "storage" - %w[all_vms vms].include?(params[:display]) ? VmOrTemplate : Storage - else - VmOrTemplate - end + def record_class + VmOrTemplate end def process_objects(objs, task, display_name = nil) - klass = get_rec_cls + klass = record_class klass_str = klass.to_s assert_rbac(klass, objs) @@ -620,7 +599,7 @@ def process_resourcepools(rps, task) # on a record # options - other optional parameters def generic_button_operation(action, action_name, operation, options = {}) - records = find_records_with_rbac(get_rec_cls, checked_or_params) + records = find_records_with_rbac(record_class, checked_or_params) if testable_action(action) && !records_support_feature?(records, action_to_feature(action)) javascript_flash( :text => _("%{action_name} action does not apply to selected items") % {:action_name => action_name}, diff --git a/app/controllers/vm_common.rb b/app/controllers/vm_common.rb index 62bb12f19ec..edb8549802e 100644 --- a/app/controllers/vm_common.rb +++ b/app/controllers/vm_common.rb @@ -87,7 +87,7 @@ def reload end def show_timeline - db = get_rec_cls + db = record_class @display = "timeline" session[:tl_record_id] = params[:id] if params[:id] @record = find_record_with_rbac(db, session[:tl_record_id]) diff --git a/spec/controllers/vm_common_spec.rb b/spec/controllers/vm_common_spec.rb index da62e8d9a55..96fe2106e50 100644 --- a/spec/controllers/vm_common_spec.rb +++ b/spec/controllers/vm_common_spec.rb @@ -408,6 +408,17 @@ end end + describe '#show_timeline' do + let(:vm) { FactoryBot.create(:vm_vmware) } + + before { controller.params = {:id => vm.id} } + + it 'gets proper record class and sets @record' do + controller.send(:show_timeline) + expect(controller.instance_variable_get(:@record)).to eq(vm) + end + end + include_examples '#download_summary_pdf', :vm_cloud include_examples '#download_summary_pdf', :vm_infra end From 7433cb8682316882a12417b3f8bf93c7865f94a1 Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Tue, 22 Oct 2019 14:49:26 +0200 Subject: [PATCH 4/7] Fix failing specs regarding record class in various controllers (cherry picked from commit 33e282feda78f9a845d6f30972cf1f168cdcadd9) --- .../ci_processing_spec.rb | 809 +++++++++--------- .../cloud_object_store_container_spec.rb | 8 +- 2 files changed, 387 insertions(+), 430 deletions(-) diff --git a/spec/controllers/application_controller/ci_processing_spec.rb b/spec/controllers/application_controller/ci_processing_spec.rb index 0a803c28adf..acb5e8e3696 100644 --- a/spec/controllers/application_controller/ci_processing_spec.rb +++ b/spec/controllers/application_controller/ci_processing_spec.rb @@ -157,480 +157,431 @@ end context "Delete object store container" do + let(:container1) { FactoryBot.create(:cloud_object_store_container) } + let(:container2) { FactoryBot.create(:cloud_object_store_container) } + before do allow(controller).to receive(:assert_rbac).and_return(nil) allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(true) - end - - let :container1 do - FactoryBot.create(:cloud_object_store_container) - end - - let :container2 do - FactoryBot.create(:cloud_object_store_container) + controller.params[:pressed] = "cloud_object_store_container_delete" end context "from list view" do - before do - controller.params[:pressed] = "cloud_object_store_container_delete" - request.parameters["controller"] = "ems_storage" - controller.instance_variable_set(:@display, "cloud_object_store_containers") - end + describe EmsStorageController do + before { controller.instance_variable_set(:@display, "cloud_object_store_containers") } - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreContainer) + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreContainer, - 'delete' - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreContainer, + 'delete' + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + end - it "invokes process_objects" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - expect(controller).to receive(:process_objects).with( - [container1.id, container2.id], - 'cloud_object_store_container_delete', - 'Delete' - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete') - end + it "invokes process_objects" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + expect(controller).to receive(:process_objects).with( + [container1.id, container2.id], + 'cloud_object_store_container_delete', + 'Delete' + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete') + end - it "invokes process_tasks on container class" do - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container1.id, container2.id], - :task => 'cloud_object_store_container_delete', - :userid => anything - ) - controller.send(:process_objects, [container1.id, container2.id], 'cloud_object_store_container_delete', - 'delete') - end + it "invokes process_tasks on container class" do + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id, container2.id], + :task => 'cloud_object_store_container_delete', + :userid => anything + ) + controller.send(:process_objects, [container1.id, container2.id], 'cloud_object_store_container_delete', + 'delete') + end - it "invokes process_tasks overall (when selected)" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container1.id, container2.id], - :task => 'cloud_object_store_container_delete', - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - end + it "invokes process_tasks overall (when selected)" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id, container2.id], + :task => 'cloud_object_store_container_delete', + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + end - it "raises an error when nothing selected" do - controller.params[:miq_grid_checks] = '' - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") }.to raise_error("Can't access records without an id") - end + it "raises an error when nothing selected" do + controller.params[:miq_grid_checks] = '' + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") }.to raise_error("Can't access records without an id") + end - it "flash - task not supported" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete does not apply to at least one of the selected items" - ) + it "flash - task not supported" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete does not apply to at least one of the selected items" + ) + end end end context "from details view" do - before do - allow(controller).to receive(:show_list).and_return(nil) - controller.params[:pressed] = "cloud_object_store_container_delete" - request.parameters["controller"] = "cloud_object_store_container" - end + describe CloudObjectStoreContainerController do + before { allow(controller).to receive(:show_list).and_return(nil) } - let :container do - FactoryBot.create(:cloud_object_store_container) - end - - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreContainer) + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreContainer, - 'delete' - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreContainer, + 'delete' + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + end - it "invokes process_objects" do - controller.params[:id] = container.id - expect(controller).to receive(:process_objects).with( - [container.id], - 'cloud_object_store_container_delete', - 'Delete' - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete') - end + it "invokes process_objects" do + controller.params[:id] = container1.id + expect(controller).to receive(:process_objects).with( + [container1.id], + 'cloud_object_store_container_delete', + 'Delete' + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete') + end - it "invokes process_tasks on container class" do - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container.id], - :task => 'cloud_object_store_container_delete', - :userid => anything - ) - controller.send(:process_objects, [container.id], 'cloud_object_store_container_delete', 'delete') - end + it "invokes process_tasks on container class" do + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id], + :task => 'cloud_object_store_container_delete', + :userid => anything + ) + controller.send(:process_objects, [container1.id], 'cloud_object_store_container_delete', 'delete') + end - it "invokes process_tasks overall" do - controller.params[:id] = container.id - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container.id], - :task => 'cloud_object_store_container_delete', - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - end + it "invokes process_tasks overall" do + controller.params[:id] = container1.id + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id], + :task => 'cloud_object_store_container_delete', + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + end - it "flash - container no longer exists" do - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") }.to raise_error("Can't access records without an id") - end + it "flash - container no longer exists" do + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") }.to raise_error("Can't access records without an id") + end - it "flash - task not supported" do - controller.params[:id] = container.id - allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete does not apply to this item" - ) + it "flash - task not supported" do + controller.params[:id] = container1.id + allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete does not apply to this item" + ) + end end end end context "Delete object store object" do + let(:object1) { FactoryBot.create(:cloud_object_store_object) } + let(:object2) { FactoryBot.create(:cloud_object_store_object) } + before do allow(controller).to receive(:assert_rbac).and_return(nil) allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(true) + controller.params[:pressed] = "cloud_object_store_object_delete" end - let :object1 do - FactoryBot.create(:cloud_object_store_object) - end + context "from list view" do + describe CloudObjectStoreContainerController do + before { controller.instance_variable_set(:@display, "cloud_object_store_objects") } - let :object2 do - FactoryBot.create(:cloud_object_store_object) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreObject) + end - context "from list view" do - before do - controller.params[:pressed] = "cloud_object_store_object_delete" - request.parameters["controller"] = "cloud_object_store_container" - controller.instance_variable_set(:@display, "cloud_object_store_objects") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreObject, + "delete" + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + end - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreObject) - end + it "invokes process_objects" do + controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" + expect(controller).to receive(:process_objects).with( + [object1.id, object2.id], + "cloud_object_store_object_delete", + "Delete" + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreObject, "delete") + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreObject, - "delete" - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - end + it "invokes process_tasks on container class" do + controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" + expect(CloudObjectStoreObject).to receive(:process_tasks).with( + :ids => [object1.id, object2.id], + :task => "cloud_object_store_object_delete", + :userid => anything + ) + controller.send(:process_objects, [object1.id, object2.id], "cloud_object_store_object_delete", "delete") + end - it "invokes process_objects" do - controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" - expect(controller).to receive(:process_objects).with( - [object1.id, object2.id], - "cloud_object_store_object_delete", - "Delete" - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreObject, "delete") - end + it "invokes process_tasks overall (when selected)" do + controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" + expect(CloudObjectStoreObject).to receive(:process_tasks).with( + :ids => [object1.id, object2.id], + :task => "cloud_object_store_object_delete", + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + end - it "invokes process_tasks on container class" do - controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" - expect(CloudObjectStoreObject).to receive(:process_tasks).with( - :ids => [object1.id, object2.id], - :task => "cloud_object_store_object_delete", - :userid => anything - ) - controller.send(:process_objects, [object1.id, object2.id], "cloud_object_store_object_delete", "delete") - end + it "invokes delete for a selected CloudObjectStoreObject" do + controller.params[:miq_grid_checks] = object1.id.to_s + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete initiated for 1 Cloud Object Store Object from the ManageIQ Database" + ) + end - it "invokes process_tasks overall (when selected)" do - controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" - expect(CloudObjectStoreObject).to receive(:process_tasks).with( - :ids => [object1.id, object2.id], - :task => "cloud_object_store_object_delete", - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - end + it "does not invoke process_tasks overall when nothing selected" do + controller.params[:miq_grid_checks] = "" + expect(CloudObjectStoreObject).not_to receive(:process_tasks) + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") + end - it "does not invoke process_tasks overall when nothing selected" do - controller.params[:miq_grid_checks] = "" - expect(CloudObjectStoreObject).not_to receive(:process_tasks) - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") - end + it "flash - nothing selected" do + controller.params[:miq_grid_checks] = "" + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") + end - it "flash - nothing selected" do - controller.params[:miq_grid_checks] = "" - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") - end + it "flash - task not supported" do + controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" + allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete does not apply to at least one of the selected items" + ) + end - it "flash - task not supported" do - controller.params[:miq_grid_checks] = "#{object1.id}, #{object2.id}" - allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete does not apply to at least one of the selected items" - ) + it "flash - task not supported for one selected item" do + controller.params[:miq_grid_checks] = object1.id.to_s + allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete does not apply to this item" + ) + end end end context "from details view" do - before do - allow(controller).to receive(:show_list).and_return(nil) - controller.params[:pressed] = "cloud_object_store_object_delete" - request.parameters["controller"] = "cloud_object_store_object" - end - - let :object do - FactoryBot.create(:cloud_object_store_object) - end + describe CloudObjectStoreObjectController do + before { allow(controller).to receive(:show_list).and_return(nil) } - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreObject) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreObject) + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreObject, - "delete" - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreObject, + "delete" + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + end - it "invokes process_objects" do - controller.params[:id] = object.id.to_s - expect(controller).to receive(:process_objects).with( - [object.id], - "cloud_object_store_object_delete", - "Delete" - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreObject, "delete") - end + it "invokes process_objects" do + controller.params[:id] = object1.id.to_s + expect(controller).to receive(:process_objects).with( + [object1.id], + "cloud_object_store_object_delete", + "Delete" + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreObject, "delete") + end - it "invokes process_tasks on object class" do - controller.params[:id] = object.id.to_s - expect(CloudObjectStoreObject).to receive(:process_tasks).with( - :ids => [object.id.to_s], - :task => "cloud_object_store_object_delete", - :userid => anything - ) - controller.send(:process_objects, [object.id.to_s], "cloud_object_store_object_delete", "delete") - end + it "invokes process_tasks on object class" do + controller.params[:id] = object1.id.to_s + expect(CloudObjectStoreObject).to receive(:process_tasks).with( + :ids => [object1.id.to_s], + :task => "cloud_object_store_object_delete", + :userid => anything + ) + controller.send(:process_objects, [object1.id.to_s], "cloud_object_store_object_delete", "delete") + end - it "invokes process_tasks overall" do - controller.params[:id] = object.id.to_s - expect(CloudObjectStoreObject).to receive(:process_tasks).with( - :ids => [object.id], - :task => "cloud_object_store_object_delete", - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - end + it "invokes process_tasks overall" do + controller.params[:id] = object1.id.to_s + expect(CloudObjectStoreObject).to receive(:process_tasks).with( + :ids => [object1.id], + :task => "cloud_object_store_object_delete", + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + end - it "flash - container no longer exists" do - object.destroy - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") - end + it "flash - container no longer exists" do + object1.destroy + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") }.to raise_error("Can't access records without an id") + end - it "flash - task not supported" do - controller.params[:id] = object.id.to_s - allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete does not apply to this item" - ) + it "flash - task not supported" do + controller.params[:id] = object1.id.to_s + allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") + expect(assigns(:flash_array).first[:message]).to include( + "Delete does not apply to this item" + ) + end end end end - context "Delete object store object" do - let :object1 do - FactoryBot.create(:cloud_object_store_object) - end - - before do - allow(controller).to receive(:assert_rbac).and_return(nil) - controller.params[:pressed] = "cloud_object_store_object_delete" - controller.params[:miq_grid_checks] = object1.id.to_s - request.parameters["controller"] = "cloud_object_store_container" - controller.instance_variable_set(:@display, "cloud_object_store_objects") - end - - it "invokes delete for a selected CloudObjectStoreObject" do - allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(true) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete initiated for 1 Cloud Object Store Object from the ManageIQ Database" - ) - end - - it "flash - task not supported" do - allow_any_instance_of(CloudObjectStoreObject).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_object_delete") - expect(assigns(:flash_array).first[:message]).to include( - "Delete does not apply to this item" - ) - end - end - context "Clear object store container" do + let(:container1) { FactoryBot.create(:cloud_object_store_container) } + let(:container2) { FactoryBot.create(:cloud_object_store_container) } + before do allow(controller).to receive(:assert_rbac).and_return(nil) allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(true) - end - - let :container1 do - FactoryBot.create(:cloud_object_store_container) - end - - let :container2 do - FactoryBot.create(:cloud_object_store_container) + controller.params[:pressed] = "cloud_object_store_container_clear" end context "from list view" do - before do - controller.params[:pressed] = "cloud_object_store_container_clear" - request.parameters["controller"] = "ems_storage" - controller.instance_variable_set(:@display, "cloud_object_store_containers") - end + describe EmsStorageController do + before { controller.instance_variable_set(:@display, "cloud_object_store_containers") } - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreContainer) + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreContainer, - 'clear' - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreContainer, + 'clear' + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + end - it "invokes process_objects" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - expect(controller).to receive(:process_objects).with( - [container1.id, container2.id], - 'cloud_object_store_container_clear', - 'Clear' - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'clear') - end + it "invokes process_objects" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + expect(controller).to receive(:process_objects).with( + [container1.id, container2.id], + 'cloud_object_store_container_clear', + 'Clear' + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'clear') + end - it "invokes process_tasks on container class" do - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container1.id, container2.id], - :task => 'cloud_object_store_container_clear', - :userid => anything - ) - controller.send(:process_objects, [container1.id, container2.id], 'cloud_object_store_container_clear', - 'clear') - end + it "invokes process_tasks on container class" do + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id, container2.id], + :task => 'cloud_object_store_container_clear', + :userid => anything + ) + controller.send(:process_objects, [container1.id, container2.id], 'cloud_object_store_container_clear', + 'clear') + end - it "invokes process_tasks overall (when selected)" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container1.id, container2.id], - :task => 'cloud_object_store_container_clear', - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - end + it "invokes process_tasks overall (when selected)" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id, container2.id], + :task => 'cloud_object_store_container_clear', + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + end - it "does not invoke process_tasks overall when nothing selected" do - controller.params[:miq_grid_checks] = '' - expect(CloudObjectStoreContainer).not_to receive(:process_tasks) - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") - end + it "does not invoke process_tasks overall when nothing selected" do + controller.params[:miq_grid_checks] = '' + expect(CloudObjectStoreContainer).not_to receive(:process_tasks) + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") + end - it "flash - nothing selected" do - controller.params[:miq_grid_checks] = '' - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") - end + it "flash - nothing selected" do + controller.params[:miq_grid_checks] = '' + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") + end - it "flash - task not supported" do - controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" - allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - expect(assigns(:flash_array).first[:message]).to include( - "Clear does not apply to at least one of the selected items" - ) + it "flash - task not supported" do + controller.params[:miq_grid_checks] = "#{container1.id}, #{container2.id}" + allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + expect(assigns(:flash_array).first[:message]).to include( + "Clear does not apply to at least one of the selected items" + ) + end end end context "from details view" do - before do - allow(controller).to receive(:show_list).and_return(nil) - controller.params[:pressed] = "cloud_object_store_container_clear" - request.parameters["controller"] = "cloud_object_store_container" - end - - let :container do - FactoryBot.create(:cloud_object_store_container) - end + describe CloudObjectStoreContainerController do + before { allow(controller).to receive(:show_list).and_return(nil) } - it "get_rec_cls" do - expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer) - end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreContainer) + end - it "invokes cloud_object_store_button_operation" do - expect(controller).to receive(:cloud_object_store_button_operation).with( - CloudObjectStoreContainer, - 'clear' - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - end + it "invokes cloud_object_store_button_operation" do + expect(controller).to receive(:cloud_object_store_button_operation).with( + CloudObjectStoreContainer, + 'clear' + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + end - it "invokes process_objects" do - controller.params[:id] = container.id - expect(controller).to receive(:process_objects).with( - [container.id], - 'cloud_object_store_container_clear', - 'Clear' - ) - controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'clear') - end + it "invokes process_objects" do + controller.params[:id] = container1.id + expect(controller).to receive(:process_objects).with( + [container1.id], + 'cloud_object_store_container_clear', + 'Clear' + ) + controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'clear') + end - it "invokes process_tasks on container class" do - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container.id], - :task => 'cloud_object_store_container_clear', - :userid => anything - ) - controller.send(:process_objects, [container.id], 'cloud_object_store_container_clear', 'clear') - end + it "invokes process_tasks on container class" do + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id], + :task => 'cloud_object_store_container_clear', + :userid => anything + ) + controller.send(:process_objects, [container1.id], 'cloud_object_store_container_clear', 'clear') + end - it "invokes process_tasks overall" do - controller.params[:id] = container.id - expect(CloudObjectStoreContainer).to receive(:process_tasks).with( - :ids => [container.id], - :task => 'cloud_object_store_container_clear', - :userid => anything - ) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - end + it "invokes process_tasks overall" do + controller.params[:id] = container1.id + expect(CloudObjectStoreContainer).to receive(:process_tasks).with( + :ids => [container1.id], + :task => 'cloud_object_store_container_clear', + :userid => anything + ) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + end - it "flash - container no longer exists" do - expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") - end + it "flash - container no longer exists" do + expect { controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") }.to raise_error("Can't access records without an id") + end - it "flash - task not supported" do - controller.params[:id] = container.id - allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) - controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") - expect(assigns(:flash_array).first[:message]).to include( - "Clear does not apply to this item" - ) + it "flash - task not supported" do + controller.params[:id] = container1.id + allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false) + controller.send(:process_cloud_object_storage_buttons, "cloud_object_store_container_clear") + expect(assigns(:flash_array).first[:message]).to include( + "Clear does not apply to this item" + ) + end end end end @@ -681,28 +632,31 @@ end context "Verify the reconfigurable flag for VMs" do + let(:vm) { FactoryBot.create(:vm_vmware) } + + before { controller.params = {:id => vm.id} } + + subject { controller.send(:get_record, "vm") } + it "Reconfigure VM action should be allowed only for a VM marked as reconfigurable" do - vm = FactoryBot.create(:vm_vmware) - controller.params = {:id => vm.id} - record = controller.send(:get_record, "vm") - action = :vm_reconfigure expect(controller).to receive(:render) - controller.send(action) - unless record.reconfigurable? + controller.send(:vm_reconfigure) + unless subject.reconfigurable? expect(controller.send(:flash_errors?)).to be_truthy expect(assigns(:flash_array).first[:message]).to include("does not apply") end end - it "Reconfigure VM action should not be allowed for a VM marked as reconfigurable" do - vm = FactoryBot.create(:vm_microsoft) - controller.params = {:id => vm.id} - record = controller.send(:get_record, "vm") - action = :vm_reconfigure - expect(controller).to receive(:render) - controller.send(action) - unless record.reconfigurable? - expect(controller.send(:flash_errors?)).to be_truthy - expect(assigns(:flash_array).first[:message]).to include("does not apply") + + context 'Microsoft provider' do + let(:vm) { FactoryBot.create(:vm_microsoft) } + + it "Reconfigure VM action should not be allowed for a VM marked as reconfigurable" do + expect(controller).to receive(:render) + controller.send(:vm_reconfigure) + unless subject.reconfigurable? + expect(controller.send(:flash_errors?)).to be_truthy + expect(assigns(:flash_array).first[:message]).to include("does not apply") + end end end end @@ -712,6 +666,7 @@ context "when a single is vm selected" do let(:supports_reconfigure_disks) { true } + before do allow(vm).to receive(:supports_reconfigure_disks?).and_return(supports_reconfigure_disks) controller.instance_variable_set(:@reconfigitems, [vm]) @@ -722,8 +677,10 @@ expect(controller.send(:supports_reconfigure_disks?)).to be_truthy end end + context "when vm does not supports reconfiguring disks" do let(:supports_reconfigure_disks) { false } + it "disables reconfigure disks" do expect(controller.send(:supports_reconfigure_disks?)).to be_falsey end @@ -732,6 +689,7 @@ context "when multiple vms selected" do let(:vm1) { FactoryBot.create(:vm_redhat) } + it "disables reconfigure disks" do controller.instance_variable_set(:@reconfigitems, [vm, vm1]) expect(controller.send(:supports_reconfigure_disks?)).to be_falsey @@ -763,14 +721,14 @@ end describe "#process_elements" do + let(:pxe) { FactoryBot.create(:pxe_server) } + it "shows passed in display name in flash message" do - pxe = FactoryBot.create(:pxe_server) controller.send(:process_elements, [pxe.id], PxeServer, 'synchronize_advertised_images_queue', 'Refresh Relationships') expect(assigns(:flash_array).first[:message]).to include("Refresh Relationships successfully initiated") end it "shows task name in flash message when display name is not passed in" do - pxe = FactoryBot.create(:pxe_server) controller.send(:process_elements, [pxe.id], PxeServer, 'synchronize_advertised_images_queue') expect(assigns(:flash_array).first[:message]) .to include("synchronize_advertised_images_queue successfully initiated") @@ -792,11 +750,12 @@ end describe "#get_record" do + let(:host) { FactoryBot.create(:host) } + + before { controller.params = {:id => host.id} } + it "use passed in db to set class for identify_record call" do - host = FactoryBot.create(:host) - controller.params = {:id => host.id} - record = controller.send(:get_record, "host") - expect(record).to be_a_kind_of(Host) + expect(controller.send(:get_record, "host")).to be_a_kind_of(Host) end end @@ -886,14 +845,15 @@ end describe "#process_objects" do - it "returns array of object ids " do - vm1 = FactoryBot.create(:vm_vmware) - vm2 = FactoryBot.create(:vm_vmware) - vm3 = FactoryBot.create(:vm_vmware) - vms = [vm1.id, vm2.id, vm3.id] - controller.send(:process_objects, vms, 'refresh_ems', 'Refresh Provider') - flash_messages = assigns(:flash_array) - expect(flash_messages.first[:message]).to include "Refresh Provider initiated for #{vms.length} VMs" + let(:vm1) { FactoryBot.create(:vm_vmware) } + let(:vm2) { FactoryBot.create(:vm_vmware) } + let(:vm3) { FactoryBot.create(:vm_vmware) } + + before { controller.params = {:display => 'vms'} } + + it "returns array of object ids" do + controller.send(:process_objects, [vm1.id, vm2.id, vm3.id], 'refresh_ems', 'Refresh Provider') + expect(controller.instance_variable_get(:@flash_array).first[:message]).to include "Refresh Provider initiated for 3 VMs" end end @@ -930,7 +890,7 @@ it "when the vm_or_template supports scan, returns false" do vm1 = FactoryBot.create(:vm_microsoft) vm2 = FactoryBot.create(:vm_vmware) - controller.params = {:miq_grid_checks => "#{vm1.id}, #{vm2.id}"} + controller.params = {:miq_grid_checks => "#{vm1.id}, #{vm2.id}", :display => 'vms'} controller.send(:generic_button_operation, 'scan', "Smartstate Analysis", @@ -943,7 +903,7 @@ vm = FactoryBot.create(:vm_vmware, :ext_management_system => FactoryBot.create(:ems_openstack_infra), :storage => FactoryBot.create(:storage)) - controller.params = {:miq_grid_checks => vm.id.to_s} + controller.params = {:miq_grid_checks => vm.id.to_s, :display => 'vms'} process_proc = controller.send(:vm_button_action) expect(process_proc).to receive(:call) controller.send(:generic_button_operation, @@ -967,7 +927,7 @@ allow(user).to receive(:role_allows?).and_return(true) end - it "should continue to retire a service and does not render flash message 'xxx does not apply xxx' " do + it "should continue to retire a service and does not render flash message 'xxx does not apply xxx'" do service = FactoryBot.create(:service) template = FactoryBot.create(:template, :ext_management_system => FactoryBot.create(:ems_openstack_infra), @@ -1103,6 +1063,7 @@ describe EmsCloudController do describe "#delete_flavor" do let!(:flavor) { FactoryBot.create(:flavor) } + before do EvmSpecHelper.create_guid_miq_server_zone stub_user(:features => :all) @@ -1123,9 +1084,7 @@ describe VmInfraController do describe '#testable_action' do - before do - controller.params = {:controller => 'vm_infra'} - end + before { controller.params = {:controller => 'vm_infra'} } context 'power operations and vm infra controller' do %w(reboot_guest reset shutdown_guest start stop suspend).each do |op| diff --git a/spec/controllers/cloud_object_store_container_spec.rb b/spec/controllers/cloud_object_store_container_spec.rb index 67555bf82be..c14378cd947 100644 --- a/spec/controllers/cloud_object_store_container_spec.rb +++ b/spec/controllers/cloud_object_store_container_spec.rb @@ -5,7 +5,7 @@ allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(true) end - context "#tags_edit" do + describe "#tags_edit" do let!(:user) { stub_user(:features => :all) } before do allow(@container).to receive(:tagged_with).with(:cat => user.userid).and_return("my tags") @@ -135,10 +135,8 @@ end end - describe "create object store container" do - before do - stub_user(:features => :all) - end + context "create object store container" do + before { stub_user(:features => :all) } shared_examples "queue create container task" do let(:task_options) do From 742bf958325838409af5fcfedfe40db765f3cfab Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Fri, 25 Oct 2019 13:02:13 +0200 Subject: [PATCH 5/7] Add new specs for record_class method for various controllers (cherry picked from commit cf2f25bf5cd87567e8370c268af144b7772793d4) --- .../ems_cluster_controller_spec.rb | 62 +++++++++++++++- spec/controllers/ems_infra_controller_spec.rb | 71 +++++++++++++------ .../ems_storage_controller_spec.rb | 13 ++++ spec/controllers/host_controller_spec.rb | 30 ++++++++ .../miq_template_controller_spec.rb | 5 ++ .../orchestration_stack_controller_spec.rb | 16 ++++- .../resource_pool_controller_spec.rb | 23 ++++-- spec/controllers/service_controller_spec.rb | 21 +++--- spec/controllers/storage_controller_spec.rb | 14 ++++ 9 files changed, 214 insertions(+), 41 deletions(-) create mode 100644 spec/controllers/miq_template_controller_spec.rb diff --git a/spec/controllers/ems_cluster_controller_spec.rb b/spec/controllers/ems_cluster_controller_spec.rb index ba6de0aa070..c6f02ffffd3 100644 --- a/spec/controllers/ems_cluster_controller_spec.rb +++ b/spec/controllers/ems_cluster_controller_spec.rb @@ -1,6 +1,7 @@ describe EmsClusterController do - context "#button" do + describe "#button" do before { allow(controller).to receive(:performed?) } + it "when VM Right Size Recommendations is pressed" do controller.params = {:pressed => "vm_right_size"} expect(controller).to receive(:vm_right_size) @@ -93,6 +94,65 @@ end end end + + context 'Smart State Analysis' do + let(:cluster) { FactoryBot.create(:ems_cluster) } + let(:vm) { FactoryBot.create(:vm_vmware) } + + before do + EvmSpecHelper.create_guid_miq_server_zone + allow(controller).to receive(:assert_privileges) + allow(controller).to receive(:drop_breadcrumb) + allow(controller).to receive(:records_support_feature?).and_return(true) + allow(controller).to receive(:render) + controller.params = {:id => cluster.id.to_s, :miq_grid_checks => vm.id.to_s, :pressed => 'vm_scan' } + end + + %w[vms all_vms].each do |display| + before { controller.instance_variable_set(:@display, display) } + + it 'initiates SSA for selected VM successfully' do + controller.send(:button) + expect(controller.instance_variable_get(:@record)).to eq(cluster) + expect(controller.instance_variable_get(:@view).db).to eq('Vm') + expect(controller.instance_variable_get(:@flash_array)).to eq([{:message => 'Analysis initiated for 1 VM and Instance from the ManageIQ Database', :level => :success}]) + end + end + + context 'nested list of Templates' do + let(:template) { FactoryBot.create(:miq_template) } + + before { controller.instance_variable_set(:@display, 'miq_templates') } + + it 'initiates SSA for selected Template successfully' do + controller.params = {:display => 'miq_templates', :id => cluster.id.to_s} + controller.send(:show) + controller.params = {:id => cluster.id.to_s, :miq_grid_checks => template.id.to_s, :pressed => 'miq_template_scan'} + controller.send(:button) + expect(controller.instance_variable_get(:@record)).to eq(cluster) + expect(controller.instance_variable_get(:@view).db).to eq('MiqTemplate') + expect(controller.instance_variable_get(:@flash_array)).to eq([{:message => 'Analysis initiated for 1 VM and Instance from the ManageIQ Database', :level => :success}]) + end + end + + context 'list of Clusters' do + before do + login_as FactoryBot.create(:user) + controller.instance_variable_set(:@display, nil) + controller.instance_variable_set(:@lastaction, 'show_list') + controller.params = {:miq_grid_checks => cluster.id.to_s, :pressed => 'ems_cluster_scan'} + end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(EmsCluster) + end + + it 'initiates SSA for Cluster' do + controller.send(:button) + expect(controller.instance_variable_get(:@flash_array)).to eq([{:message => 'Cluster / Deployment Role: scan successfully initiated', :level => :success}]) + end + end + end end describe "#show" do diff --git a/spec/controllers/ems_infra_controller_spec.rb b/spec/controllers/ems_infra_controller_spec.rb index 44c5f280510..ec042645867 100644 --- a/spec/controllers/ems_infra_controller_spec.rb +++ b/spec/controllers/ems_infra_controller_spec.rb @@ -1,7 +1,8 @@ describe EmsInfraController do let!(:server) { EvmSpecHelper.local_miq_server(:zone => zone) } let(:zone) { FactoryBot.build(:zone) } - context "#button" do + + describe "#button" do before do stub_user(:features => :all) EvmSpecHelper.create_guid_miq_server_zone @@ -90,6 +91,40 @@ post :button, :params => {:pressed => "vm_transform_mass", :id => ems_infra.id, :format => :js} expect(controller.send(:flash_errors?)).not_to be_truthy end + + context 'operations on Clusters, Orchestration Stacks, Datastores of selected Provider' do + before do + controller.params = {:pressed => pressed} + controller.instance_variable_set(:@display, display) + end + + context 'SSA on selected Clusters from a nested list' do + let(:pressed) { 'ems_cluster_scan' } + let(:display) { 'ems_clusters' } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(EmsCluster) + end + end + + context 'retirement for Orchestration Stacks displayed in a nested list' do + let(:pressed) { 'orchestration_stack_retire_now' } + let(:display) { 'orchestration_stacks' } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(OrchestrationStack) + end + end + + context 'SSA on selected Datastores from a nested list' do + let(:pressed) { 'storage_scan' } + let(:display) { 'storages' } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(Storage) + end + end + end end describe "#create" do @@ -434,11 +469,12 @@ it { expect(response.status).to eq(200) } end - describe "breadcrumbs path on a 'show' page of an Infrastructure Provider accessed from Dashboard maintab" do + context "breadcrumbs path on a 'show' page of an Infrastructure Provider accessed from Dashboard maintab" do before do stub_user(:features => :all) EvmSpecHelper.create_guid_miq_server_zone end + context "when previous breadcrumbs path contained 'Cloud Providers'" do it "shows 'Infrastructure Providers -> (Summary)' breadcrumb path" do ems = FactoryBot.create(:ems_vmware) @@ -451,9 +487,8 @@ end describe "#build_credentials" do - before do - @ems = FactoryBot.create(:ems_openstack_infra) - end + before { @ems = FactoryBot.create(:ems_openstack_infra) } + context "#build_credentials only contains credentials that it supports and has a username for in params" do let(:default_creds) { {:userid => "default_userid", :password => "default_password"} } let(:amqp_creds) { {:userid => "amqp_userid", :password => "amqp_password"} } @@ -493,10 +528,8 @@ end end - describe "SCVMM - create, update, validate, cancel" do - before do - login_as FactoryBot.create(:user, :features => %w(ems_infra_new ems_infra_edit)) - end + context "SCVMM - create, update, validate, cancel" do + before { login_as FactoryBot.create(:user, :features => %w[ems_infra_new ems_infra_edit]) } render_views @@ -583,10 +616,8 @@ end end - describe "Openstack - create, update" do - before do - login_as FactoryBot.create(:user, :features => %w(ems_infra_new ems_infra_edit)) - end + context "Openstack - create, update" do + before { login_as FactoryBot.create(:user, :features => %w[ems_infra_new ems_infra_edit]) } render_views @@ -664,7 +695,7 @@ end end - describe "Redhat - create, update" do + context "Redhat - create, update" do before do login_as FactoryBot.create(:user, :features => %w(ems_infra_new ems_infra_edit)) allow_any_instance_of(ManageIQ::Providers::Redhat::InfraManager) @@ -767,10 +798,8 @@ end end - describe "Kubevirt - update" do - before do - login_as FactoryBot.create(:user, :features => %w(ems_infra_new ems_infra_edit)) - end + context "Kubevirt - update" do + before { login_as FactoryBot.create(:user, :features => %w[ems_infra_new ems_infra_edit]) } render_views @@ -842,10 +871,8 @@ end end - describe "VMWare - create, update" do - before do - login_as FactoryBot.create(:user, :features => %w(ems_infra_new ems_infra_edit)) - end + context "VMWare - create, update" do + before { login_as FactoryBot.create(:user, :features => %w[ems_infra_new ems_infra_edit]) } render_views diff --git a/spec/controllers/ems_storage_controller_spec.rb b/spec/controllers/ems_storage_controller_spec.rb index b6949115639..8497833a36c 100644 --- a/spec/controllers/ems_storage_controller_spec.rb +++ b/spec/controllers/ems_storage_controller_spec.rb @@ -40,4 +40,17 @@ expect(assigns(:ems).id).to eq(ems_storage.id) end end + + describe '#button' do + context 'tagging Cloud Object Store Container' do + before do + controller.params = {:pressed => 'cloud_object_store_container_tag'} + controller.instance_variable_set(:@display, 'cloud_object_store_containers') + end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(CloudObjectStoreContainer) + end + end + end end diff --git a/spec/controllers/host_controller_spec.rb b/spec/controllers/host_controller_spec.rb index 699104034f6..3a53c55867c 100644 --- a/spec/controllers/host_controller_spec.rb +++ b/spec/controllers/host_controller_spec.rb @@ -127,6 +127,10 @@ expect(controller.send(:flash_errors?)).not_to be_truthy end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(Host) + end + context 'provisioning VMS displayed through details page of a Host' do before do allow(controller).to receive(:process_vm_buttons) @@ -142,6 +146,32 @@ expect(controller).to receive(:render_or_redirect_partial).with('vm') controller.send(:button) end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(VmOrTemplate) + end + end + + context 'SSA on Templates displayed through details page of a Host' do + before do + controller.params = {:pressed => 'miq_template_scan'} + controller.instance_variable_set(:@display, 'miq_templates') + end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(VmOrTemplate) + end + end + + context 'SSA on Datastores displayed through details page of a Host' do + before do + controller.params = {:pressed => 'storage_scan'} + controller.instance_variable_set(:@display, 'storages') + end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(Storage) + end end end diff --git a/spec/controllers/miq_template_controller_spec.rb b/spec/controllers/miq_template_controller_spec.rb new file mode 100644 index 00000000000..44d147d4b35 --- /dev/null +++ b/spec/controllers/miq_template_controller_spec.rb @@ -0,0 +1,5 @@ +describe MiqTemplateController do + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(MiqTemplate) + end +end diff --git a/spec/controllers/orchestration_stack_controller_spec.rb b/spec/controllers/orchestration_stack_controller_spec.rb index 094fb544e08..9adc968e126 100644 --- a/spec/controllers/orchestration_stack_controller_spec.rb +++ b/spec/controllers/orchestration_stack_controller_spec.rb @@ -1,9 +1,7 @@ describe OrchestrationStackController do let!(:user) { stub_user(:features => :all) } - before do - EvmSpecHelper.create_guid_miq_server_zone - end + before { EvmSpecHelper.create_guid_miq_server_zone } render_views @@ -229,5 +227,17 @@ def validate_format expect(controller.send(:flash_errors?)).not_to be_truthy end end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(OrchestrationStack) + end + + context 'Instances displayed through Relationships of Orchestration Stack' do + before { controller.params = {:display => 'instances'} } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(VmOrTemplate) + end + end end end diff --git a/spec/controllers/resource_pool_controller_spec.rb b/spec/controllers/resource_pool_controller_spec.rb index 011cad73813..aba673167d8 100644 --- a/spec/controllers/resource_pool_controller_spec.rb +++ b/spec/controllers/resource_pool_controller_spec.rb @@ -1,8 +1,6 @@ describe ResourcePoolController do - context "#button" do - before do - controller.instance_variable_set(:@display, "vms") - end + describe "#button" do + before { controller.instance_variable_set(:@display, "vms") } it "when VM Right Size Recommendations is pressed" do controller.params = {:pressed => "vm_right_size"} @@ -55,6 +53,20 @@ expect(controller.send(:flash_errors?)).not_to be_truthy end + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(ResourcePool) + end + + context 'VMs displayed through Relationships of a Resource Pool' do + %w[all_vms vms].each do |display| + before { controller.params = {:display => display} } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(VmOrTemplate) + end + end + end + context 'reconfigure VMs' do before do controller.instance_variable_set(:@display, 'vms') @@ -121,6 +133,7 @@ context "Direct VMs" do let(:url_params) { { :display => "vms" } } + it "renders" do bypass_rescue expect(subject).to have_http_status(200) @@ -129,6 +142,7 @@ context "All VMs" do let(:url_params) { { :display => "all_vms" } } + it "renders" do bypass_rescue expect(subject).to have_http_status(200) @@ -137,6 +151,7 @@ context "Nested Resource Pools" do let(:url_params) { { :display => "resource_pools"} } + it "renders" do bypass_rescue expect(subject).to have_http_status(200) diff --git a/spec/controllers/service_controller_spec.rb b/spec/controllers/service_controller_spec.rb index 85493aab1df..2b4909c5115 100644 --- a/spec/controllers/service_controller_spec.rb +++ b/spec/controllers/service_controller_spec.rb @@ -112,10 +112,8 @@ end end - describe 'x_button' do - before do - ApplicationController.handle_exceptions = true - end + describe '#x_button' do + before { ApplicationController.handle_exceptions = true } describe 'corresponding methods are called for allowed actions' do ServiceController::SERVICE_X_BUTTON_ALLOWED_ACTIONS.each_pair do |action_name, method| @@ -237,6 +235,10 @@ expect(response.status).to eq(200) expect(response.body).to include('service/tagging_edit') end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(Service) + end end end @@ -341,9 +343,8 @@ context 'displaying a list of All Services' do describe '#tree_select' do - before do - allow(controller).to receive(:data_for_breadcrumbs).and_return([{:title => "title", :action => "action", :key => "key"}]) - end + before { allow(controller).to receive(:data_for_breadcrumbs).and_return([{:title => "title", :action => "action", :key => "key"}]) } + render_views let(:service_search) { FactoryBot.create(:miq_search, :description => 'a', :db => 'Service') } @@ -397,9 +398,7 @@ context 'searching text' do let(:search) { "Service" } - before do - controller.instance_variable_set(:@search_text, search) - end + before { controller.instance_variable_set(:@search_text, search) } it 'updates right cell text properly' do controller.send(:get_node_info, "root") @@ -447,7 +446,7 @@ end end - describe "helpers" do + context "helpers" do describe "generic_objects_list?" do it "returns true when user is in generic_objects section" do get :show, :params => { :id => service_with_go.id, :display => 'generic_objects'} diff --git a/spec/controllers/storage_controller_spec.rb b/spec/controllers/storage_controller_spec.rb index 1d8423db13e..b9b95f2cb1a 100644 --- a/spec/controllers/storage_controller_spec.rb +++ b/spec/controllers/storage_controller_spec.rb @@ -92,6 +92,20 @@ expect(flash_messages.first[:level]).to eq(:success) end end + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(Storage) + end + + context 'nested list of VMs' do + %w[all_vms vms].each do |display| + before { controller.params = {:display => display} } + + it 'returns proper record class' do + expect(controller.send(:record_class)).to eq(VmOrTemplate) + end + end + end end context 'render_views' do From b4e2114f89077d2f0f62be3d9a46e889b0898c79 Mon Sep 17 00:00:00 2001 From: Milan Zazrivec Date: Tue, 28 Jul 2020 12:10:48 +0200 Subject: [PATCH 6/7] Revert "Changed `record_class` back to use 'get_rec_cls'" This reverts commit 751ec5359e08c2166a0ea7ec7fbbdb436b4dc8a7. --- app/controllers/application_controller/ci_processing.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller/ci_processing.rb b/app/controllers/application_controller/ci_processing.rb index 47a5d85eca4..6f01c199b0a 100644 --- a/app/controllers/application_controller/ci_processing.rb +++ b/app/controllers/application_controller/ci_processing.rb @@ -389,7 +389,7 @@ def retirevms_now def check_compliance_vms assert_privileges(params[:pressed]) - records = find_records_with_rbac(get_rec_cls, checked_or_params) + records = find_records_with_rbac(record_class, checked_or_params) # Check each record if there is any compliance policy assigned to it if records.any? { |record| !record.has_compliance_policies? } javascript_flash( From 6504ca0abb9d6ac6bd8057917095e76f01e99484 Mon Sep 17 00:00:00 2001 From: Hilda Stastna Date: Wed, 9 Oct 2019 11:11:09 +0200 Subject: [PATCH 7/7] Display only one Cancel button for Compare action Issue: https://github.com/ManageIQ/manageiq-ui-classic/issues/6263 (cherry picked from commit ef9fed402a82cd6827722a12c9a576707f5afcf3) --- app/controllers/application_controller/compare.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/application_controller/compare.rb b/app/controllers/application_controller/compare.rb index 2548c326759..3c32c6dbb5e 100644 --- a/app/controllers/application_controller/compare.rb +++ b/app/controllers/application_controller/compare.rb @@ -1207,6 +1207,7 @@ def compare_to_json(view) @grid_cols_json = @cols.to_json.to_s.html_safe @lastaction = "compare_miq" + @explorer = true if request.xml_http_request? && explorer_controller? end def compare_build_record_rows(view, section, records, fields)