diff options
Diffstat (limited to 'spec')
28 files changed, 425 insertions, 1584 deletions
diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb index 7dafb813545..8fcc3a7fccf 100644 --- a/spec/controllers/groups/uploads_controller_spec.rb +++ b/spec/controllers/groups/uploads_controller_spec.rb @@ -35,6 +35,169 @@ RSpec.describe Groups::UploadsController do end end + describe "GET #show" do + let(:filename) { "rails_sample.jpg" } + let(:user) { create(:user) } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } + let(:secret) { FileUploader.generate_secret } + let(:uploader_class) { FileUploader } + + let(:upload_service) do + UploadService.new(model, jpg, uploader_class).execute + end + + let(:show_upload) do + get :show, params: params.merge(secret: secret, filename: filename) + end + + before do + allow(FileUploader).to receive(:generate_secret).and_return(secret) + + allow_next_instance_of(FileUploader) do |instance| + allow(instance).to receive(:image?).and_return(true) + end + + upload_service + end + + context 'when the group is public' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with appropriate status" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + + context 'when the group is private' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with appropriate status" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + end + def post_authorize(verified: true) request.headers.merge!(workhorse_internal_api_request_header) if verified diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb deleted file mode 100644 index f8cee09006c..00000000000 --- a/spec/controllers/projects/serverless/functions_controller_spec.rb +++ /dev/null @@ -1,341 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::Serverless::FunctionsController do - include KubernetesHelpers - include ReactiveCachingHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) } - let(:service) { cluster.platform_kubernetes } - let(:environment) { create(:environment, project: project) } - let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) } - let(:knative_services_finder) { environment.knative_services_finder } - let(:function_description) { 'A serverless function' } - let(:function_name) { 'some-function-name' } - let(:knative_stub_options) do - { namespace: namespace.namespace, name: function_name, description: function_description } - end - - let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } - - let(:namespace) do - create(:cluster_kubernetes_namespace, - cluster: cluster, - cluster_project: cluster.cluster_project, - project: cluster.cluster_project.project, - environment: environment) - end - - before do - project.add_maintainer(user) - sign_in(user) - end - - def params(opts = {}) - opts.reverse_merge(namespace_id: project.namespace.to_param, - project_id: project.to_param) - end - - shared_examples_for 'behind :deprecated_serverless feature flag' do - before do - stub_feature_flags(deprecated_serverless: false) - end - - it 'returns 404' do - action - expect(response).to have_gitlab_http_status(:not_found) - end - end - - describe 'GET #index' do - let(:expected_json) { { 'knative_installed' => knative_state, 'functions' => functions } } - - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :index, params: params({ format: :json }) } - end - - context 'when cache is being read' do - let(:knative_state) { 'checking' } - let(:functions) { [] } - - before do - get :index, params: params({ format: :json }) - end - - it 'returns checking' do - expect(json_response).to eq expected_json - end - - it { expect(response).to have_gitlab_http_status(:ok) } - end - - context 'when cache is ready' do - let(:knative_state) { true } - - before do - allow(Clusters::KnativeServicesFinder) - .to receive(:new) - .and_return(knative_services_finder) - synchronous_reactive_cache(knative_services_finder) - stub_kubeclient_service_pods( - kube_response({ "kind" => "PodList", "items" => [] }), - namespace: namespace.namespace - ) - end - - context 'when no functions were found' do - let(:functions) { [] } - - before do - stub_kubeclient_knative_services( - namespace: namespace.namespace, - response: kube_response({ "kind" => "ServiceList", "items" => [] }) - ) - get :index, params: params({ format: :json }) - end - - it 'returns checking' do - expect(json_response).to eq expected_json - end - - it { expect(response).to have_gitlab_http_status(:ok) } - end - - context 'when functions were found' do - let(:functions) { [{}, {}] } - - before do - stub_kubeclient_knative_services(namespace: namespace.namespace, cluster_id: cluster.id, name: function_name) - end - - it 'returns functions' do - get :index, params: params({ format: :json }) - expect(json_response["functions"]).not_to be_empty - end - - it 'filters out the functions whose cluster the user does not have permission to read' do - allow(controller).to receive(:can?).and_return(true) - expect(controller).to receive(:can?).with(user, :read_cluster, cluster).and_return(false) - - get :index, params: params({ format: :json }) - - expect(json_response["functions"]).to be_empty - end - - it 'returns a successful response status' do - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - end - - context 'when there is serverless domain for a cluster' do - let!(:serverless_domain_cluster) do - create(:serverless_domain_cluster, clusters_applications_knative_id: knative.id) - end - - it 'returns JSON with function details with serverless domain URL' do - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response["functions"]).not_to be_empty - - expect(json_response["functions"]).to all( - include( - 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}" - ) - ) - end - end - - context 'when there is no serverless domain for a cluster' do - it 'keeps function URL as it was' do - expect(::Serverless::Domain).not_to receive(:new) - - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - end - end - end - end - end - - describe 'GET #show' do - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :show, params: params({ format: :json, environment_id: "*", id: "foo" }) } - end - - context 'with function that does not exist' do - it 'returns 404' do - get :show, params: params({ format: :json, environment_id: "*", id: "foo" }) - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'with valid data', :use_clean_rails_memory_store_caching do - shared_examples 'GET #show with valid data' do - context 'when there is serverless domain for a cluster' do - let!(:serverless_domain_cluster) do - create(:serverless_domain_cluster, clusters_applications_knative_id: knative.id) - end - - it 'returns JSON with function details with serverless domain URL' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}" - ) - end - - it 'returns 404 when user does not have permission to read the cluster' do - allow(controller).to receive(:can?).and_return(true) - expect(controller).to receive(:can?).with(user, :read_cluster, cluster).and_return(false) - - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'when there is no serverless domain for a cluster' do - it 'keeps function URL as it was' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com" - ) - end - end - - it 'return json with function details' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'name' => function_name, - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com", - 'description' => function_description, - 'podcount' => 0 - ) - end - end - - context 'on Knative 0.5.0' do - before do - prepare_knative_stubs(knative_05_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.6.0' do - before do - prepare_knative_stubs(knative_06_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.7.0' do - before do - prepare_knative_stubs(knative_07_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.9.0' do - before do - prepare_knative_stubs(knative_09_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - end - end - - describe 'GET #metrics' do - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :metrics, params: params({ format: :json, environment_id: "*", id: "foo" }) } - end - - context 'invalid data' do - it 'has a bad function name' do - get :metrics, params: params({ format: :json, environment_id: "*", id: "foo" }) - expect(response).to have_gitlab_http_status(:no_content) - end - end - end - - describe 'GET #index with data', :use_clean_rails_memory_store_caching do - shared_examples 'GET #index with data' do - it 'has data' do - get :index, params: params({ format: :json }) - - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to match({ - 'knative_installed' => 'checking', - 'functions' => [ - a_hash_including( - 'name' => function_name, - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com", - 'description' => function_description - ) - ] - }) - end - - it 'has data in html' do - get :index, params: params - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context 'on Knative 0.5.0' do - before do - prepare_knative_stubs(knative_05_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.6.0' do - before do - prepare_knative_stubs(knative_06_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.7.0' do - before do - prepare_knative_stubs(knative_07_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.9.0' do - before do - prepare_knative_stubs(knative_09_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - end - - def prepare_knative_stubs(knative_service) - stub_kubeclient_service_pods - stub_reactive_cache(knative_services_finder, - { - services: [knative_service], - pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"] - }, - *knative_services_finder.cache_args) - end -end diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb index c008c7253d8..6d2db25ade2 100644 --- a/spec/controllers/projects/uploads_controller_spec.rb +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -54,6 +54,241 @@ RSpec.describe Projects::UploadsController do end end + describe "GET #show" do + let(:filename) { "rails_sample.jpg" } + let(:user) { create(:user) } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } + let(:secret) { FileUploader.generate_secret } + let(:uploader_class) { FileUploader } + + let(:upload_service) do + UploadService.new(model, jpg, uploader_class).execute + end + + let(:show_upload) do + get :show, params: params.merge(secret: secret, filename: filename) + end + + before do + allow(FileUploader).to receive(:generate_secret).and_return(secret) + + allow_next_instance_of(FileUploader) do |instance| + allow(instance).to receive(:image?).and_return(true) + end + + upload_service + end + + context 'when project is private do' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 302" do + show_upload + + expect(response).to have_gitlab_http_status(:redirect) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 404" do + show_upload + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + + context 'when project is public' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + end + def post_authorize(verified: true) request.headers.merge!(workhorse_internal_api_request_header) if verified diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index f4f3530639b..a69317032ef 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -863,7 +863,8 @@ RSpec.describe ProjectsController do id: project.path, project: { project_setting_attributes: { - show_default_award_emojis: boolean_value + show_default_award_emojis: boolean_value, + enforce_auth_checks_on_uploads: boolean_value } } } @@ -871,6 +872,7 @@ RSpec.describe ProjectsController do project.reload expect(project.show_default_award_emojis?).to eq(result) + expect(project.enforce_auth_checks_on_uploads?).to eq(result) end end end diff --git a/spec/features/monitor_sidebar_link_spec.rb b/spec/features/monitor_sidebar_link_spec.rb index fcef0fa0eff..3c59cd65cdb 100644 --- a/spec/features/monitor_sidebar_link_spec.rb +++ b/spec/features/monitor_sidebar_link_spec.rb @@ -45,7 +45,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project)) expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project)) - expect(page).not_to have_link('Serverless', href: project_serverless_functions_path(project)) expect(page).not_to have_link('Logs', href: project_logs_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -79,7 +78,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project)) expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project)) - expect(page).not_to have_link('Serverless', href: project_serverless_functions_path(project)) expect(page).not_to have_link('Logs', href: project_logs_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -98,7 +96,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) - expect(page).not_to have_link('Serverless', href: project_serverless_functions_path(project)) expect(page).not_to have_link('Logs', href: project_logs_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -117,7 +114,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project)) expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).to have_link('Logs', href: project_logs_path(project)) - expect(page).to have_link('Serverless', href: project_serverless_functions_path(project)) expect(page).to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -134,7 +130,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Environments', href: project_environments_path(project)) expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project)) expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) - expect(page).to have_link('Serverless', href: project_serverless_functions_path(project)) expect(page).to have_link('Logs', href: project_logs_path(project)) expect(page).to have_link('Kubernetes', href: project_clusters_path(project)) end diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb deleted file mode 100644 index db8c2a24f2f..00000000000 --- a/spec/features/projects/serverless/functions_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Functions', :js do - include KubernetesHelpers - include ReactiveCachingHelpers - - let(:project) { create(:project, :repository) } - let(:user) { create(:user) } - - before do - project.add_maintainer(user) - gitlab_sign_in(user) - end - - shared_examples "it's missing knative installation" do - before do - functions_finder = Projects::Serverless::FunctionsFinder.new(project) - visit project_serverless_functions_path(project) - allow(Projects::Serverless::FunctionsFinder) - .to receive(:new) - .and_return(functions_finder) - synchronous_reactive_cache(functions_finder) - end - - it 'sees an empty state require Knative installation' do - expect(page).to have_selector('.empty-state') - end - end - - context 'when user does not have a cluster and visits the serverless page' do - it_behaves_like "it's missing knative installation" - end - - context 'when the user does have a cluster and visits the serverless page' do - let(:cluster) { create(:cluster, :project, :provided_by_gcp) } - - it_behaves_like "it's missing knative installation" - end - - context 'when the user has a cluster and knative installed and visits the serverless page', :kubeclient do - let(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) } - let(:service) { cluster.platform_kubernetes } - let(:environment) { create(:environment, project: project) } - let!(:deployment) { create(:deployment, :success, cluster: cluster, environment: environment) } - let(:knative_services_finder) { environment.knative_services_finder } - let(:namespace) do - create(:cluster_kubernetes_namespace, - cluster: cluster, - project: cluster.cluster_project.project, - environment: environment) - end - - before do - allow(Clusters::KnativeServicesFinder) - .to receive(:new) - .and_return(knative_services_finder) - synchronous_reactive_cache(knative_services_finder) - stub_kubeclient_knative_services(stub_get_services_options) - stub_kubeclient_service_pods(nil, namespace: namespace.namespace) - visit project_serverless_functions_path(project) - end - - context 'when there are no functions' do - let(:stub_get_services_options) do - { - namespace: namespace.namespace, - response: kube_response({ "kind" => "ServiceList", "items" => [] }) - } - end - - it 'sees an empty listing of serverless functions' do - expect(page).to have_selector('.empty-state') - expect(page).not_to have_selector('.content-list') - end - end - - context 'when there are functions' do - let(:stub_get_services_options) { { namespace: namespace.namespace } } - - it 'does not see an empty listing of serverless functions' do - expect(page).not_to have_selector('.empty-state') - expect(page).to have_selector('.content-list') - end - end - end -end diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb deleted file mode 100644 index 9b58da2e398..00000000000 --- a/spec/finders/projects/serverless/functions_finder_spec.rb +++ /dev/null @@ -1,185 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::Serverless::FunctionsFinder do - include KubernetesHelpers - include PrometheusHelpers - include ReactiveCachingHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) } - let(:service) { cluster.platform_kubernetes } - let(:environment) { create(:environment, project: project) } - let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) } - let(:knative_services_finder) { environment.knative_services_finder } - - let(:namespace) do - create(:cluster_kubernetes_namespace, - cluster: cluster, - project: project, - environment: environment) - end - - before do - project.add_maintainer(user) - end - - describe '#knative_installed' do - context 'when environment does not exist yet' do - shared_examples 'before first deployment' do - let(:service) { cluster.platform_kubernetes } - let(:deployment) { nil } - - it 'returns true if Knative is installed on cluster' do - stub_kubeclient_discover_knative_found(service.api_url) - function_finder = described_class.new(project) - synchronous_reactive_cache(function_finder) - - expect(function_finder.knative_installed).to be true - end - - it 'returns false if Knative is not installed on cluster' do - stub_kubeclient_discover_knative_not_found(service.api_url) - function_finder = described_class.new(project) - synchronous_reactive_cache(function_finder) - - expect(function_finder.knative_installed).to be false - end - end - - context 'when project level cluster is present and enabled' do - it_behaves_like 'before first deployment' do - let(:cluster) { create(:cluster, :project, :provided_by_gcp, enabled: true) } - let(:project) { cluster.project } - end - end - - context 'when group level cluster is present and enabled' do - it_behaves_like 'before first deployment' do - let(:cluster) { create(:cluster, :group, :provided_by_gcp, enabled: true) } - let(:project) { create(:project, group: cluster.groups.first) } - end - end - - context 'when instance level cluster is present and enabled' do - it_behaves_like 'before first deployment' do - let(:project) { create(:project) } - let(:cluster) { create(:cluster, :instance, :provided_by_gcp, enabled: true) } - end - end - - context 'when project level cluster is present, but disabled' do - let(:cluster) { create(:cluster, :project, :provided_by_gcp, enabled: false) } - let(:project) { cluster.project } - let(:service) { cluster.platform_kubernetes } - let(:deployment) { nil } - - it 'returns false even if Knative is installed on cluster' do - stub_kubeclient_discover_knative_found(service.api_url) - function_finder = described_class.new(project) - synchronous_reactive_cache(function_finder) - - expect(function_finder.knative_installed).to be false - end - end - end - - context 'when reactive_caching is still fetching data' do - it 'returns "checking"' do - expect(described_class.new(project).knative_installed).to eq 'checking' - end - end - - context 'when reactive_caching has finished' do - before do - allow(Clusters::KnativeServicesFinder) - .to receive(:new) - .and_return(knative_services_finder) - synchronous_reactive_cache(knative_services_finder) - end - - context 'when knative is not installed' do - it 'returns false' do - stub_kubeclient_discover_knative_not_found(service.api_url) - - expect(described_class.new(project).knative_installed).to eq false - end - end - - context 'reactive_caching is finished and knative is installed' do - it 'returns true' do - stub_kubeclient_knative_services(namespace: namespace.namespace) - stub_kubeclient_service_pods(nil, namespace: namespace.namespace) - - expect(described_class.new(project).knative_installed).to be true - end - end - end - end - - describe 'retrieve data from knative' do - context 'does not have knative installed' do - it { expect(described_class.new(project).execute).to be_empty } - end - - context 'has knative installed' do - let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } - let(:finder) { described_class.new(project) } - - it 'there are no functions' do - expect(finder.execute).to be_empty - end - - it 'there are functions', :use_clean_rails_memory_store_caching do - stub_kubeclient_service_pods - stub_reactive_cache(knative_services_finder, - { - services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"], - pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"] - }, - *knative_services_finder.cache_args) - - expect(finder.execute).not_to be_empty - end - - it 'has a function', :use_clean_rails_memory_store_caching do - stub_kubeclient_service_pods - stub_reactive_cache(knative_services_finder, - { - services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"], - pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"] - }, - *knative_services_finder.cache_args) - - result = finder.service(cluster.environment_scope, cluster.project.name) - expect(result).to be_present - expect(result.name).to be_eql(cluster.project.name) - end - - it 'has metrics', :use_clean_rails_memory_store_caching do - end - end - - context 'has prometheus' do - let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) } - let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } - let!(:prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) } - let(:finder) { described_class.new(project) } - - before do - allow(Gitlab::Prometheus::Adapter).to receive(:new).and_return(double(prometheus_adapter: prometheus_adapter)) - allow(prometheus_adapter).to receive(:query).and_return(prometheus_empty_body('matrix')) - end - - it 'is available' do - expect(finder.has_prometheus?("*")).to be true - end - - it 'has query data' do - expect(finder.invocation_metrics("*", cluster.project.name)).not_to be_nil - end - end - end -end diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap deleted file mode 100644 index 0f4dfdf8a75..00000000000 --- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EmptyStateComponent should render content 1`] = ` -"<section class=\\"gl-display-flex empty-state gl-text-center gl-flex-direction-column\\"> - <div class=\\"gl-max-w-full\\"> - <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"\\" role=\\"img\\" class=\\"gl-max-w-full gl-dark-invert-keep-hue\\"></div> - </div> - <div class=\\"gl-max-w-full gl-m-auto\\"> - <div class=\\"gl-mx-auto gl-my-0 gl-p-5\\"> - <h1 class=\\"gl-font-size-h-display gl-line-height-36 h4\\"> - Getting started with serverless - </h1> - <p class=\\"gl-mt-3\\">Serverless was <gl-link-stub target=\\"_blank\\" href=\\"https://about.gitlab.com/releases/2021/09/22/gitlab-14-3-released/#gitlab-serverless\\">deprecated</gl-link-stub>. But if you opt to use it, you must install Knative in your Kubernetes cluster first. <gl-link-stub href=\\"/help\\">Learn more.</gl-link-stub> - </p> - <div class=\\"gl-display-flex gl-flex-wrap gl-justify-content-center\\"> - <!----> - <!----> - </div> - </div> - </div> -</section>" -`; diff --git a/spec/frontend/serverless/components/area_spec.js b/spec/frontend/serverless/components/area_spec.js deleted file mode 100644 index 05c9ee44307..00000000000 --- a/spec/frontend/serverless/components/area_spec.js +++ /dev/null @@ -1,121 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Area from '~/serverless/components/area.vue'; -import { mockNormalizedMetrics } from '../mock_data'; - -describe('Area component', () => { - const mockWidgets = 'mockWidgets'; - const mockGraphData = mockNormalizedMetrics; - let areaChart; - - beforeEach(() => { - areaChart = shallowMount(Area, { - propsData: { - graphData: mockGraphData, - containerWidth: 0, - }, - slots: { - default: mockWidgets, - }, - }); - }); - - afterEach(() => { - areaChart.destroy(); - }); - - it('renders chart title', () => { - expect(areaChart.find({ ref: 'graphTitle' }).text()).toBe(mockGraphData.title); - }); - - it('contains graph widgets from slot', () => { - expect(areaChart.find({ ref: 'graphWidgets' }).text()).toBe(mockWidgets); - }); - - describe('methods', () => { - describe('formatTooltipText', () => { - const mockDate = mockNormalizedMetrics.queries[0].result[0].values[0].time; - const generateSeriesData = (type) => ({ - seriesData: [ - { - componentSubType: type, - value: [mockDate, 4], - }, - ], - value: mockDate, - }); - - describe('series is of line type', () => { - beforeEach(() => { - areaChart.vm.formatTooltipText(generateSeriesData('line')); - }); - - it('formats tooltip title', () => { - expect(areaChart.vm.tooltipPopoverTitle).toBe('28 Feb 2019, 11:11AM'); - }); - - it('formats tooltip content', () => { - expect(areaChart.vm.tooltipPopoverContent).toBe('Invocations (requests): 4'); - }); - }); - - it('verify default interval value of 1', () => { - expect(areaChart.vm.getInterval).toBe(1); - }); - }); - - describe('onResize', () => { - const mockWidth = 233; - - beforeEach(() => { - jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({ - width: mockWidth, - })); - areaChart.vm.onResize(); - }); - - it('sets area chart width', () => { - expect(areaChart.vm.width).toBe(mockWidth); - }); - }); - }); - - describe('computed', () => { - describe('chartData', () => { - it('utilizes all data points', () => { - expect(Object.keys(areaChart.vm.chartData)).toEqual(['requests']); - expect(areaChart.vm.chartData.requests.length).toBe(2); - }); - - it('creates valid data', () => { - const data = areaChart.vm.chartData.requests; - - expect( - data.filter( - (datum) => new Date(datum.time).getTime() > 0 && typeof datum.value === 'number', - ).length, - ).toBe(data.length); - }); - }); - - describe('generateSeries', () => { - it('utilizes correct time data', () => { - expect(areaChart.vm.generateSeries.data).toEqual([ - ['2019-02-28T11:11:38.756Z', 0], - ['2019-02-28T11:12:38.756Z', 0], - ]); - }); - }); - - describe('xAxisLabel', () => { - it('constructs a label for the chart x-axis', () => { - expect(areaChart.vm.xAxisLabel).toBe('invocations / minute'); - }); - }); - - describe('yAxisLabel', () => { - it('constructs a label for the chart y-axis', () => { - expect(areaChart.vm.yAxisLabel).toBe('Invocations (requests)'); - }); - }); - }); -}); diff --git a/spec/frontend/serverless/components/empty_state_spec.js b/spec/frontend/serverless/components/empty_state_spec.js deleted file mode 100644 index d63882c2a6d..00000000000 --- a/spec/frontend/serverless/components/empty_state_spec.js +++ /dev/null @@ -1,25 +0,0 @@ -import { GlEmptyState, GlSprintf } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import EmptyStateComponent from '~/serverless/components/empty_state.vue'; -import { createStore } from '~/serverless/store'; - -describe('EmptyStateComponent', () => { - let wrapper; - - beforeEach(() => { - const store = createStore({ - clustersPath: '/clusters', - helpPath: '/help', - emptyImagePath: '/image.svg', - }); - wrapper = shallowMount(EmptyStateComponent, { store, stubs: { GlEmptyState, GlSprintf } }); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('should render content', () => { - expect(wrapper.html()).toMatchSnapshot(); - }); -}); diff --git a/spec/frontend/serverless/components/environment_row_spec.js b/spec/frontend/serverless/components/environment_row_spec.js deleted file mode 100644 index 944283136d0..00000000000 --- a/spec/frontend/serverless/components/environment_row_spec.js +++ /dev/null @@ -1,68 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import environmentRowComponent from '~/serverless/components/environment_row.vue'; - -import { translate } from '~/serverless/utils'; -import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data'; - -const createComponent = (env, envName) => - shallowMount(environmentRowComponent, { - propsData: { env, envName }, - }).vm; - -describe('environment row component', () => { - describe('default global cluster case', () => { - let vm; - - beforeEach(() => { - vm = createComponent(translate(mockServerlessFunctions.functions)['*'], '*'); - }); - - afterEach(() => vm.$destroy()); - - it('has the correct envId', () => { - expect(vm.envId).toEqual('env-global'); - }); - - it('is open by default', () => { - expect(vm.isOpenClass).toEqual({ 'is-open': true }); - }); - - it('generates correct output', () => { - expect(vm.$el.id).toEqual('env-global'); - expect(vm.$el.classList.contains('is-open')).toBe(true); - expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('*'); - }); - - it('opens and closes correctly', () => { - expect(vm.isOpen).toBe(true); - - vm.toggleOpen(); - - expect(vm.isOpen).toBe(false); - }); - }); - - describe('default named cluster case', () => { - let vm; - - beforeEach(() => { - vm = createComponent(translate(mockServerlessFunctionsDiffEnv.functions).test, 'test'); - }); - - afterEach(() => vm.$destroy()); - - it('has the correct envId', () => { - expect(vm.envId).toEqual('env-test'); - }); - - it('is open by default', () => { - expect(vm.isOpenClass).toEqual({ 'is-open': true }); - }); - - it('generates correct output', () => { - expect(vm.$el.id).toEqual('env-test'); - expect(vm.$el.classList.contains('is-open')).toBe(true); - expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('test'); - }); - }); -}); diff --git a/spec/frontend/serverless/components/function_details_spec.js b/spec/frontend/serverless/components/function_details_spec.js deleted file mode 100644 index 0c9b2498589..00000000000 --- a/spec/frontend/serverless/components/function_details_spec.js +++ /dev/null @@ -1,100 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; -import Vuex from 'vuex'; - -import functionDetailsComponent from '~/serverless/components/function_details.vue'; -import { createStore } from '~/serverless/store'; - -describe('functionDetailsComponent', () => { - let component; - let store; - - beforeEach(() => { - Vue.use(Vuex); - - store = createStore({ clustersPath: '/clusters', helpPath: '/help' }); - }); - - afterEach(() => { - component.vm.$destroy(); - }); - - describe('Verify base functionality', () => { - const serviceStub = { - name: 'test', - description: 'a description', - environment: '*', - url: 'http://service.com/test', - namespace: 'test-ns', - podcount: 0, - metricsUrl: '/metrics', - }; - - it('has a name, description, URL, and no pods loaded', () => { - component = shallowMount(functionDetailsComponent, { - store, - propsData: { - func: serviceStub, - hasPrometheus: false, - }, - }); - - expect( - component.vm.$el.querySelector('.serverless-function-name').innerHTML.trim(), - ).toContain('test'); - - expect( - component.vm.$el.querySelector('.serverless-function-description').innerHTML.trim(), - ).toContain('a description'); - - expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain( - 'No pods loaded at this time.', - ); - }); - - it('has a pods loaded', () => { - serviceStub.podcount = 1; - - component = shallowMount(functionDetailsComponent, { - store, - propsData: { - func: serviceStub, - hasPrometheus: false, - }, - }); - - expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain('1 pod in use'); - }); - - it('has multiple pods loaded', () => { - serviceStub.podcount = 3; - - component = shallowMount(functionDetailsComponent, { - store, - propsData: { - func: serviceStub, - hasPrometheus: false, - }, - }); - - expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain('3 pods in use'); - }); - - it('can support a missing description', () => { - serviceStub.description = null; - - component = shallowMount(functionDetailsComponent, { - store, - propsData: { - func: serviceStub, - hasPrometheus: false, - }, - }); - - expect( - component.vm.$el.querySelector('.serverless-function-description').querySelector('div') - .innerHTML.length, - ).toEqual(0); - }); - }); -}); diff --git a/spec/frontend/serverless/components/function_row_spec.js b/spec/frontend/serverless/components/function_row_spec.js deleted file mode 100644 index 081edd33b3b..00000000000 --- a/spec/frontend/serverless/components/function_row_spec.js +++ /dev/null @@ -1,34 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import functionRowComponent from '~/serverless/components/function_row.vue'; -import Timeago from '~/vue_shared/components/time_ago_tooltip.vue'; - -import { mockServerlessFunction } from '../mock_data'; - -describe('functionRowComponent', () => { - let wrapper; - - const createComponent = (func) => { - wrapper = shallowMount(functionRowComponent, { - propsData: { func }, - }); - }; - - afterEach(() => { - wrapper.destroy(); - }); - - it('Parses the function details correctly', () => { - createComponent(mockServerlessFunction); - - expect(wrapper.find('b').text()).toBe(mockServerlessFunction.name); - expect(wrapper.find('span').text()).toBe(mockServerlessFunction.image); - expect(wrapper.find(Timeago).attributes('time')).not.toBe(null); - }); - - it('handles clicks correctly', () => { - createComponent(mockServerlessFunction); - const { vm } = wrapper; - - expect(vm.checkClass(vm.$el.querySelector('p'))).toBe(true); // check somewhere inside the row - }); -}); diff --git a/spec/frontend/serverless/components/functions_spec.js b/spec/frontend/serverless/components/functions_spec.js deleted file mode 100644 index 846fd63e918..00000000000 --- a/spec/frontend/serverless/components/functions_spec.js +++ /dev/null @@ -1,86 +0,0 @@ -import { GlLoadingIcon, GlAlert, GlSprintf } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; -import AxiosMockAdapter from 'axios-mock-adapter'; -import Vuex from 'vuex'; -import { TEST_HOST } from 'helpers/test_constants'; -import axios from '~/lib/utils/axios_utils'; -import EmptyState from '~/serverless/components/empty_state.vue'; -import EnvironmentRow from '~/serverless/components/environment_row.vue'; -import functionsComponent from '~/serverless/components/functions.vue'; -import { createStore } from '~/serverless/store'; -import { mockServerlessFunctions } from '../mock_data'; - -describe('functionsComponent', () => { - const statusPath = `${TEST_HOST}/statusPath`; - - let component; - let store; - let axiosMock; - - beforeEach(() => { - axiosMock = new AxiosMockAdapter(axios); - axiosMock.onGet(statusPath).reply(200); - - Vue.use(Vuex); - - store = createStore({}); - component = shallowMount(functionsComponent, { store, stubs: { GlSprintf } }); - }); - - afterEach(() => { - component.destroy(); - axiosMock.restore(); - }); - - it('should render deprecation notice', () => { - expect(component.findComponent(GlAlert).text()).toBe( - 'Serverless was deprecated in GitLab 14.3.', - ); - }); - - it('should render empty state when Knative is not installed', async () => { - await store.dispatch('receiveFunctionsSuccess', { knative_installed: false }); - - expect(component.findComponent(EmptyState).exists()).toBe(true); - }); - - it('should render a loading component', async () => { - await store.dispatch('requestFunctionsLoading'); - - expect(component.findComponent(GlLoadingIcon).exists()).toBe(true); - }); - - it('should render empty state when there is no function data', async () => { - await store.dispatch('receiveFunctionsNoDataSuccess', { knative_installed: true }); - - expect( - component.vm.$el - .querySelector('.empty-state, .js-empty-state') - .classList.contains('js-empty-state'), - ).toBe(true); - - expect(component.vm.$el.querySelector('.state-title, .text-center').innerHTML.trim()).toEqual( - 'No functions available', - ); - }); - - it('should render functions and a loader when functions are partially fetched', async () => { - await store.dispatch('receiveFunctionsPartial', { - ...mockServerlessFunctions, - knative_installed: 'checking', - }); - - expect(component.find('.js-functions-wrapper').exists()).toBe(true); - expect(component.find('.js-functions-loader').exists()).toBe(true); - }); - - it('should render the functions list', async () => { - store = createStore({ clustersPath: 'clustersPath', helpPath: 'helpPath', statusPath }); - - await component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions); - - await nextTick(); - expect(component.findComponent(EnvironmentRow).exists()).toBe(true); - }); -}); diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js deleted file mode 100644 index 1b93fd784e1..00000000000 --- a/spec/frontend/serverless/components/missing_prometheus_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import { GlButton } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import missingPrometheusComponent from '~/serverless/components/missing_prometheus.vue'; -import { createStore } from '~/serverless/store'; - -describe('missingPrometheusComponent', () => { - let wrapper; - - const createComponent = (missingData) => { - const store = createStore({ clustersPath: '/clusters', helpPath: '/help' }); - - wrapper = shallowMount(missingPrometheusComponent, { store, propsData: { missingData } }); - }; - - afterEach(() => { - wrapper.destroy(); - }); - - it('should render missing prometheus message', () => { - createComponent(false); - const { vm } = wrapper; - - expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain( - 'Function invocation metrics require the Prometheus cluster integration.', - ); - - expect(wrapper.find(GlButton).attributes('variant')).toBe('success'); - }); - - it('should render no prometheus data message', () => { - createComponent(true); - const { vm } = wrapper; - - expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain( - 'Invocation metrics loading or not available at this time.', - ); - }); -}); diff --git a/spec/frontend/serverless/components/pod_box_spec.js b/spec/frontend/serverless/components/pod_box_spec.js deleted file mode 100644 index cf0c14a2cac..00000000000 --- a/spec/frontend/serverless/components/pod_box_spec.js +++ /dev/null @@ -1,22 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import podBoxComponent from '~/serverless/components/pod_box.vue'; - -const createComponent = (count) => - shallowMount(podBoxComponent, { - propsData: { - count, - }, - }).vm; - -describe('podBoxComponent', () => { - it('should render three boxes', () => { - const count = 3; - const vm = createComponent(count); - const rects = vm.$el.querySelectorAll('rect'); - - expect(rects.length).toEqual(3); - expect(parseInt(rects[2].getAttribute('x'), 10)).toEqual(40); - - vm.$destroy(); - }); -}); diff --git a/spec/frontend/serverless/components/url_spec.js b/spec/frontend/serverless/components/url_spec.js deleted file mode 100644 index 8c839577aa0..00000000000 --- a/spec/frontend/serverless/components/url_spec.js +++ /dev/null @@ -1,26 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; -import urlComponent from '~/serverless/components/url.vue'; -import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; - -const createComponent = (uri) => - shallowMount(Vue.extend(urlComponent), { - propsData: { - uri, - }, - }); - -describe('urlComponent', () => { - it('should render correctly', () => { - const uri = 'http://testfunc.apps.example.com'; - const wrapper = createComponent(uri); - const { vm } = wrapper; - - expect(vm.$el.classList.contains('clipboard-group')).toBe(true); - expect(wrapper.find(ClipboardButton).attributes('text')).toEqual(uri); - - expect(vm.$el.querySelector('[data-testid="url-text-field"]').innerHTML).toContain(uri); - - vm.$destroy(); - }); -}); diff --git a/spec/frontend/serverless/mock_data.js b/spec/frontend/serverless/mock_data.js deleted file mode 100644 index 1816ad62a04..00000000000 --- a/spec/frontend/serverless/mock_data.js +++ /dev/null @@ -1,145 +0,0 @@ -export const mockServerlessFunctions = { - knative_installed: true, - functions: [ - { - name: 'testfunc1', - namespace: 'tm-example', - environment_scope: '*', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc1', - podcount: null, - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc1.tm-example.apps.example.com', - description: 'A test service', - image: 'knative-test-container-buildtemplate', - }, - { - name: 'testfunc2', - namespace: 'tm-example', - environment_scope: '*', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc2', - podcount: null, - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc2.tm-example.apps.example.com', - description: 'A second test service\nThis one with additional descriptions', - image: 'knative-test-echo-buildtemplate', - }, - ], -}; - -export const mockServerlessFunctionsDiffEnv = { - knative_installed: true, - functions: [ - { - name: 'testfunc1', - namespace: 'tm-example', - environment_scope: '*', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc1', - podcount: null, - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc1.tm-example.apps.example.com', - description: 'A test service', - image: 'knative-test-container-buildtemplate', - }, - { - name: 'testfunc2', - namespace: 'tm-example', - environment_scope: 'test', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc2', - podcount: null, - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc2.tm-example.apps.example.com', - description: 'A second test service\nThis one with additional descriptions', - image: 'knative-test-echo-buildtemplate', - }, - ], -}; - -export const mockServerlessFunction = { - name: 'testfunc1', - namespace: 'tm-example', - environment_scope: '*', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc1', - podcount: '3', - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc1.tm-example.apps.example.com', - description: 'A test service', - image: 'knative-test-container-buildtemplate', -}; - -export const mockMultilineServerlessFunction = { - name: 'testfunc1', - namespace: 'tm-example', - environment_scope: '*', - cluster_id: 46, - detail_url: '/testuser/testproj/serverless/functions/*/testfunc1', - podcount: '3', - created_at: '2019-02-05T01:01:23Z', - url: 'http://testfunc1.tm-example.apps.example.com', - description: 'testfunc1\nA test service line\\nWith additional services', - image: 'knative-test-container-buildtemplate', -}; - -export const mockMetrics = { - success: true, - last_update: '2019-02-28T19:11:38.926Z', - metrics: { - id: 22, - title: 'Knative function invocations', - required_metrics: ['container_memory_usage_bytes', 'container_cpu_usage_seconds_total'], - weight: 0, - y_label: 'Invocations', - queries: [ - { - query_range: - 'floor(sum(rate(istio_revision_request_count{destination_configuration="%{function_name}", destination_namespace="%{kube_namespace}"}[1m])*30))', - unit: 'requests', - label: 'invocations / minute', - result: [ - { - metric: {}, - values: [ - [1551352298.756, '0'], - [1551352358.756, '0'], - ], - }, - ], - }, - ], - }, -}; - -export const mockNormalizedMetrics = { - id: 22, - title: 'Knative function invocations', - required_metrics: ['container_memory_usage_bytes', 'container_cpu_usage_seconds_total'], - weight: 0, - y_label: 'Invocations', - queries: [ - { - query_range: - 'floor(sum(rate(istio_revision_request_count{destination_configuration="%{function_name}", destination_namespace="%{kube_namespace}"}[1m])*30))', - unit: 'requests', - label: 'invocations / minute', - result: [ - { - metric: {}, - values: [ - { - time: '2019-02-28T11:11:38.756Z', - value: 0, - }, - { - time: '2019-02-28T11:12:38.756Z', - value: 0, - }, - ], - }, - ], - }, - ], -}; diff --git a/spec/frontend/serverless/store/actions_spec.js b/spec/frontend/serverless/store/actions_spec.js deleted file mode 100644 index 5fbecf081a6..00000000000 --- a/spec/frontend/serverless/store/actions_spec.js +++ /dev/null @@ -1,80 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import testAction from 'helpers/vuex_action_helper'; -import axios from '~/lib/utils/axios_utils'; -import statusCodes from '~/lib/utils/http_status'; -import { fetchFunctions, fetchMetrics } from '~/serverless/store/actions'; -import { mockServerlessFunctions, mockMetrics } from '../mock_data'; -import { adjustMetricQuery } from '../utils'; - -describe('ServerlessActions', () => { - let mock; - - beforeEach(() => { - mock = new MockAdapter(axios); - }); - - afterEach(() => { - mock.restore(); - }); - - describe('fetchFunctions', () => { - it('should successfully fetch functions', () => { - const endpoint = '/functions'; - mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockServerlessFunctions)); - - return testAction( - fetchFunctions, - { functionsPath: endpoint }, - {}, - [], - [ - { type: 'requestFunctionsLoading' }, - { type: 'receiveFunctionsSuccess', payload: mockServerlessFunctions }, - ], - ); - }); - - it('should successfully retry', () => { - const endpoint = '/functions'; - mock - .onGet(endpoint) - .reply(() => new Promise((resolve) => setTimeout(() => resolve(200), Infinity))); - - return testAction( - fetchFunctions, - { functionsPath: endpoint }, - {}, - [], - [{ type: 'requestFunctionsLoading' }], - ); - }); - }); - - describe('fetchMetrics', () => { - it('should return no prometheus', () => { - const endpoint = '/metrics'; - mock.onGet(endpoint).reply(statusCodes.NO_CONTENT); - - return testAction( - fetchMetrics, - { metricsPath: endpoint, hasPrometheus: false }, - {}, - [], - [{ type: 'receiveMetricsNoPrometheus' }], - ); - }); - - it('should successfully fetch metrics', () => { - const endpoint = '/metrics'; - mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockMetrics)); - - return testAction( - fetchMetrics, - { metricsPath: endpoint, hasPrometheus: true }, - {}, - [], - [{ type: 'receiveMetricsSuccess', payload: adjustMetricQuery(mockMetrics) }], - ); - }); - }); -}); diff --git a/spec/frontend/serverless/store/getters_spec.js b/spec/frontend/serverless/store/getters_spec.js deleted file mode 100644 index e1942bd2759..00000000000 --- a/spec/frontend/serverless/store/getters_spec.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as getters from '~/serverless/store/getters'; -import serverlessState from '~/serverless/store/state'; -import { mockServerlessFunctions } from '../mock_data'; - -describe('Serverless Store Getters', () => { - let state; - - beforeEach(() => { - state = serverlessState; - }); - - describe('hasPrometheusMissingData', () => { - it('should return false if Prometheus is not installed', () => { - state.hasPrometheus = false; - - expect(getters.hasPrometheusMissingData(state)).toEqual(false); - }); - - it('should return false if Prometheus is installed and there is data', () => { - state.hasPrometheusData = true; - - expect(getters.hasPrometheusMissingData(state)).toEqual(false); - }); - - it('should return true if Prometheus is installed and there is no data', () => { - state.hasPrometheus = true; - state.hasPrometheusData = false; - - expect(getters.hasPrometheusMissingData(state)).toEqual(true); - }); - }); - - describe('getFunctions', () => { - it('should translate the raw function array to group the functions per environment scope', () => { - state.functions = mockServerlessFunctions.functions; - - const funcs = getters.getFunctions(state); - - expect(Object.keys(funcs)).toContain('*'); - expect(funcs['*'].length).toEqual(2); - }); - }); -}); diff --git a/spec/frontend/serverless/store/mutations_spec.js b/spec/frontend/serverless/store/mutations_spec.js deleted file mode 100644 index a1a8f9a2ca7..00000000000 --- a/spec/frontend/serverless/store/mutations_spec.js +++ /dev/null @@ -1,86 +0,0 @@ -import * as types from '~/serverless/store/mutation_types'; -import mutations from '~/serverless/store/mutations'; -import { mockServerlessFunctions, mockMetrics } from '../mock_data'; - -describe('ServerlessMutations', () => { - describe('Functions List Mutations', () => { - it('should ensure loading is true', () => { - const state = {}; - - mutations[types.REQUEST_FUNCTIONS_LOADING](state); - - expect(state.isLoading).toEqual(true); - }); - - it('should set proper state once functions are loaded', () => { - const state = {}; - - mutations[types.RECEIVE_FUNCTIONS_SUCCESS](state, mockServerlessFunctions); - - expect(state.isLoading).toEqual(false); - expect(state.hasFunctionData).toEqual(true); - expect(state.functions).toEqual(mockServerlessFunctions.functions); - }); - - it('should ensure loading has stopped and hasFunctionData is false when there are no functions available', () => { - const state = {}; - - mutations[types.RECEIVE_FUNCTIONS_NODATA_SUCCESS](state, { knative_installed: true }); - - expect(state.isLoading).toEqual(false); - expect(state.hasFunctionData).toEqual(false); - expect(state.functions).toBe(undefined); - }); - - it('should ensure loading has stopped, and an error is raised', () => { - const state = {}; - - mutations[types.RECEIVE_FUNCTIONS_ERROR](state, 'sample error'); - - expect(state.isLoading).toEqual(false); - expect(state.hasFunctionData).toEqual(false); - expect(state.functions).toBe(undefined); - expect(state.error).not.toBe(undefined); - }); - }); - - describe('Function Details Metrics Mutations', () => { - it('should ensure isLoading and hasPrometheus data flags indicate data is loaded', () => { - const state = {}; - - mutations[types.RECEIVE_METRICS_SUCCESS](state, mockMetrics); - - expect(state.isLoading).toEqual(false); - expect(state.hasPrometheusData).toEqual(true); - expect(state.graphData).toEqual(mockMetrics); - }); - - it('should ensure isLoading and hasPrometheus data flags are cleared indicating no functions available', () => { - const state = {}; - - mutations[types.RECEIVE_METRICS_NODATA_SUCCESS](state); - - expect(state.isLoading).toEqual(false); - expect(state.hasPrometheusData).toEqual(false); - expect(state.graphData).toBe(undefined); - }); - - it('should properly indicate an error', () => { - const state = {}; - - mutations[types.RECEIVE_METRICS_ERROR](state, 'sample error'); - - expect(state.hasPrometheusData).toEqual(false); - expect(state.error).not.toBe(undefined); - }); - - it('should properly indicate when prometheus is installed', () => { - const state = {}; - - mutations[types.RECEIVE_METRICS_NO_PROMETHEUS](state); - - expect(state.hasPrometheus).toEqual(false); - expect(state.hasPrometheusData).toEqual(false); - }); - }); -}); diff --git a/spec/frontend/serverless/utils.js b/spec/frontend/serverless/utils.js deleted file mode 100644 index 7caf7da231e..00000000000 --- a/spec/frontend/serverless/utils.js +++ /dev/null @@ -1,17 +0,0 @@ -export const adjustMetricQuery = (data) => { - const updatedMetric = data.metrics; - - const queries = data.metrics.queries.map((query) => ({ - ...query, - result: query.result.map((result) => ({ - ...result, - values: result.values.map(([timestamp, value]) => ({ - time: new Date(timestamp * 1000).toISOString(), - value: Number(value), - })), - })), - })); - - updatedMetric.queries = queries; - return updatedMetric; -}; diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb index 9a4d7bd996e..e69edbe6dc0 100644 --- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb @@ -274,8 +274,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do it 'instantiates a Client' do allow(project).to receive(:import_data).and_return(double(credentials: credentials)) expect(Gitlab::LegacyGithubImport::Client).to receive(:new).with( - credentials[:user], - **{} + credentials[:user] ) subject.client diff --git a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb index 81114f5a0b3..2da7d324708 100644 --- a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb @@ -39,27 +39,17 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do subject.renderable_items.delete(find_menu_item(:kubernetes)) end - it 'menu link points to Serverless page' do - expect(subject.link).to eq find_menu_item(:serverless).link + it 'menu link points to Terraform page' do + expect(subject.link).to eq find_menu_item(:terraform).link end - context 'when Serverless menu is not visible' do + context 'when Terraform menu is not visible' do before do - subject.renderable_items.delete(find_menu_item(:serverless)) + subject.renderable_items.delete(find_menu_item(:terraform)) end - it 'menu link points to Terraform page' do - expect(subject.link).to eq find_menu_item(:terraform).link - end - - context 'when Terraform menu is not visible' do - before do - subject.renderable_items.delete(find_menu_item(:terraform)) - end - - it 'menu link points to Google Cloud page' do - expect(subject.link).to eq find_menu_item(:google_cloud).link - end + it 'menu link points to Google Cloud page' do + expect(subject.link).to eq find_menu_item(:google_cloud).link end end end @@ -88,20 +78,6 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do it_behaves_like 'access rights checks' end - describe 'Serverless' do - let(:item_id) { :serverless } - - it_behaves_like 'access rights checks' - - context 'when feature :deprecated_serverless is disabled' do - before do - stub_feature_flags(deprecated_serverless: false) - end - - it { is_expected.to be_nil } - end - end - describe 'Terraform' do let(:item_id) { :terraform } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6066822f4f1..dc0fa6eff66 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -845,6 +845,9 @@ RSpec.describe Project, factory_default: :keep do warn_about_potentially_unwanted_characters warn_about_potentially_unwanted_characters= warn_about_potentially_unwanted_characters? + enforce_auth_checks_on_uploads + enforce_auth_checks_on_uploads= + enforce_auth_checks_on_uploads? ).each do |method| it { is_expected.to delegate_method(method).to(:project_setting).with_arguments(allow_nil: true) } end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5f623eda28a..20d371bdd4b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -3563,6 +3563,20 @@ RSpec.describe API::Projects do expect(json_response['topics']).to eq(%w[topic2]) end + it 'updates enforce_auth_checks_on_uploads' do + project3.update!(enforce_auth_checks_on_uploads: false) + + project_param = { enforce_auth_checks_on_uploads: true } + + expect { put api("/projects/#{project3.id}", user), params: project_param } + .to change { project3.reload.enforce_auth_checks_on_uploads } + .from(false) + .to(true) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['enforce_auth_checks_on_uploads']).to eq(true) + end + it 'updates squash_option' do project3.update!(squash_option: 'always') diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index b472819a00b..ef6ff7be840 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -76,7 +76,6 @@ RSpec.shared_context 'project navbar structure' do nav_item: _('Infrastructure'), nav_sub_items: [ _('Kubernetes clusters'), - _('Serverless platform'), _('Terraform') ] }, diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index 22e925e22ae..3943355bffd 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -537,24 +537,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do end describe 'Infrastructure' do - describe 'Serverless platform' do - it 'has a link to the serverless page' do - render - - expect(rendered).to have_link('Serverless platform', href: project_serverless_functions_path(project)) - end - - describe 'when the user does not have access' do - let(:user) { nil } - - it 'does not have a link to the serverless page' do - render - - expect(rendered).not_to have_link('Serverless platform') - end - end - end - describe 'Terraform' do it 'has a link to the terraform page' do render |