diff options
Diffstat (limited to 'spec')
10 files changed, 289 insertions, 46 deletions
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb index a71e34fd1ca..71c3833bd2d 100644 --- a/spec/controllers/concerns/metrics_dashboard_spec.rb +++ b/spec/controllers/concerns/metrics_dashboard_spec.rb @@ -31,11 +31,13 @@ describe MetricsDashboard do end context 'when params are provided' do + let(:params) { { environment: environment } } + before do allow(controller).to receive(:project).and_return(project) allow(controller) .to receive(:metrics_dashboard_params) - .and_return(environment: environment) + .and_return(params) end it 'returns the specified dashboard' do @@ -43,6 +45,15 @@ describe MetricsDashboard do expect(json_response).not_to have_key('all_dashboards') end + context 'when the params are in an alternate format' do + let(:params) { ActionController::Parameters.new({ environment: environment }).permit! } + + it 'returns the specified dashboard' do + expect(json_response['dashboard']['dashboard']).to eq('Environment metrics') + expect(json_response).not_to have_key('all_dashboards') + end + end + context 'when parameters are provided and the list of all dashboards is required' do before do allow(controller).to receive(:include_all_dashboards?).and_return(true) diff --git a/spec/controllers/projects/grafana_api_controller_spec.rb b/spec/controllers/projects/grafana_api_controller_spec.rb index 352a364295b..96a12efdcfc 100644 --- a/spec/controllers/projects/grafana_api_controller_spec.rb +++ b/spec/controllers/projects/grafana_api_controller_spec.rb @@ -94,4 +94,87 @@ describe Projects::GrafanaApiController do end end end + + describe 'GET #metrics_dashboard' do + let(:service_result) { { status: :success, dashboard: '{}' } } + let(:params) do + { + format: :json, + embedded: true, + grafana_url: 'https://grafana.example.com', + namespace_id: project.namespace.full_path, + project_id: project.name + } + end + + before do + allow(Gitlab::Metrics::Dashboard::Finder) + .to receive(:find) + .and_return(service_result) + end + + context 'when the result is still processing' do + let(:service_result) { nil } + + it 'returns 204 no content' do + get :metrics_dashboard, params: params + + expect(response).to have_gitlab_http_status(:no_content) + end + end + + context 'when the result was successful' do + it 'returns the dashboard response' do + get :metrics_dashboard, params: params + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({ + 'dashboard' => '{}', + 'status' => 'success' + }) + end + end + + context 'when an error has occurred' do + shared_examples_for 'error response' do |http_status| + it "returns #{http_status}" do + get :metrics_dashboard, params: params + + expect(response).to have_gitlab_http_status(http_status) + expect(json_response['status']).to eq('error') + expect(json_response['message']).to eq('error message') + end + end + + context 'with an error accessing grafana' do + let(:service_result) do + { + http_status: :service_unavailable, + status: :error, + message: 'error message' + } + end + + it_behaves_like 'error response', :service_unavailable + end + + context 'with a processing error' do + let(:service_result) { { status: :error, message: 'error message' } } + + it_behaves_like 'error response', :bad_request + end + end + + context 'when grafana embeds are not enabled' do + before do + stub_feature_flags(gfm_grafana_integration: false) + end + + it 'returns 403 immediately' do + get :metrics_dashboard, params: params + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + end end diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb index 0f60cd42748..7b969aea547 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -28,6 +28,7 @@ describe 'User uses header search field', :js do context 'when using the keyboard shortcut' do before do + find('#search.js-autocomplete-disabled') find('body').native.send_keys('s') end diff --git a/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb new file mode 100644 index 00000000000..81053469e7a --- /dev/null +++ b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Banzai::Filter::InlineGrafanaMetricsFilter do + include FilterSpecHelper + + let_it_be(:project) { create(:project) } + let_it_be(:grafana_integration) { create(:grafana_integration, project: project) } + + let(:input) { %(<a href="#{url}">example</a>) } + let(:doc) { filter(input) } + + let(:url) { grafana_integration.grafana_url + dashboard_path } + let(:dashboard_path) do + '/d/XDaNK6amz/gitlab-omnibus-redis' \ + '?from=1570397739557&to=1570484139557' \ + '&var-instance=All&panelId=14' + end + + context 'when feature flag is disabled' do + before do + stub_feature_flags(gfm_grafana_integration: false) + end + + it 'leaves the markdown unchanged' do + expect(unescape(doc.to_s)).to eq(input) + end + end + + it 'appends a metrics charts placeholder with dashboard url after metrics links' do + node = doc.at_css('.js-render-metrics') + expect(node).to be_present + + dashboard_url = urls.project_grafana_api_metrics_dashboard_url( + project, + embedded: true, + grafana_url: url, + start: "2019-10-06T21:35:39Z", + end: "2019-10-07T21:35:39Z" + ) + + expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url) + end + + context 'when the dashboard link is part of a paragraph' do + let(:paragraph) { %(This is an <a href="#{url}">example</a> of metrics.) } + let(:input) { %(<p>#{paragraph}</p>) } + + it 'appends the charts placeholder after the enclosing paragraph' do + expect(unescape(doc.at_css('p').to_s)).to include(paragraph) + expect(doc.at_css('.js-render-metrics')).to be_present + end + end + + context 'when grafana is not configured' do + before do + allow(project).to receive(:grafana_integration).and_return(nil) + end + + it 'leaves the markdown unchanged' do + expect(unescape(doc.to_s)).to eq(input) + end + end + + context 'when parameters are missing' do + let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis' } + + it 'leaves the markdown unchanged' do + expect(unescape(doc.to_s)).to eq(input) + end + end + + private + + # Nokogiri escapes the URLs, but we don't care about that + # distinction for the purposes of this filter + def unescape(html) + CGI.unescapeHTML(html) + end +end diff --git a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb index a99cd7d6076..745b9133529 100644 --- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb +++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb @@ -18,30 +18,48 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do end context 'with a metrics charts placeholder' do - let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) } + shared_examples_for 'a supported metrics dashboard url' do + context 'no user is logged in' do + it 'redacts the placeholder' do + expect(doc.to_s).to be_empty + end + end - context 'no user is logged in' do - it 'redacts the placeholder' do - expect(doc.to_s).to be_empty + context 'the user does not have permission do see charts' do + let(:doc) { filter(input, current_user: build(:user)) } + + it 'redacts the placeholder' do + expect(doc.to_s).to be_empty + end end - end - context 'the user does not have permission do see charts' do - let(:doc) { filter(input, current_user: build(:user)) } + context 'the user has requisite permissions' do + let(:user) { create(:user) } + let(:doc) { filter(input, current_user: user) } - it 'redacts the placeholder' do - expect(doc.to_s).to be_empty + it 'leaves the placeholder' do + project.add_maintainer(user) + + expect(doc.to_s).to eq input + end end end - context 'the user has requisite permissions' do - let(:user) { create(:user) } - let(:doc) { filter(input, current_user: user) } + let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) } - it 'leaves the placeholder' do - project.add_maintainer(user) + it_behaves_like 'a supported metrics dashboard url' + + context 'for a grafana dashboard' do + let(:url) { urls.project_grafana_api_metrics_dashboard_url(project, embedded: true) } + + it_behaves_like 'a supported metrics dashboard url' + end - expect(doc.to_s).to eq input + context 'for an internal non-dashboard url' do + let(:url) { urls.project_url(project) } + + it 'leaves the placeholder' do + expect(doc.to_s).to be_empty end end end diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb index 095d0a2df78..0d4562f78f1 100644 --- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb @@ -75,6 +75,17 @@ describe Gitlab::Metrics::Dashboard::ServiceSelector do it { is_expected.to be Metrics::Dashboard::CustomMetricEmbedService } end + + context 'with a grafana link' do + let(:arguments) do + { + embedded: true, + grafana_url: 'https://grafana.example.com' + } + end + + it { is_expected.to be Metrics::Dashboard::GrafanaMetricEmbedService } + end end end end diff --git a/spec/lib/gitlab/metrics/dashboard/url_spec.rb b/spec/lib/gitlab/metrics/dashboard/url_spec.rb index e0dc6d98efc..daaf66cba46 100644 --- a/spec/lib/gitlab/metrics/dashboard/url_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/url_spec.rb @@ -3,13 +3,41 @@ require 'spec_helper' describe Gitlab::Metrics::Dashboard::Url do - describe '#regex' do - it 'returns a regular expression' do - expect(described_class.regex).to be_a Regexp - end + shared_examples_for 'a regex which matches the expected url' do + it { is_expected.to be_a Regexp } it 'matches a metrics dashboard link with named params' do - url = Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url( + expect(subject).to match url + + subject.match(url) do |m| + expect(m.named_captures).to eq expected_params + end + end + end + + shared_examples_for 'does not match non-matching urls' do + it 'does not match other gitlab urls that contain the term metrics' do + url = Gitlab::Routing.url_helpers.active_common_namespace_project_prometheus_metrics_url('foo', 'bar', :json) + + expect(subject).not_to match url + end + + it 'does not match other gitlab urls' do + url = Gitlab.config.gitlab.url + + expect(subject).not_to match url + end + + it 'does not match non-gitlab urls' do + url = 'https://www.super_awesome_site.com/' + + expect(subject).not_to match url + end + end + + describe '#regex' do + let(:url) do + Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url( 'foo', 'bar', 1, @@ -18,8 +46,10 @@ describe Gitlab::Metrics::Dashboard::Url do group: 'awesome group', anchor: 'title' ) + end - expected_params = { + let(:expected_params) do + { 'url' => url, 'namespace' => 'foo', 'project' => 'bar', @@ -27,31 +57,40 @@ describe Gitlab::Metrics::Dashboard::Url do 'query' => '?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z', 'anchor' => '#title' } - - expect(described_class.regex).to match url - - described_class.regex.match(url) do |m| - expect(m.named_captures).to eq expected_params - end end - it 'does not match other gitlab urls that contain the term metrics' do - url = Gitlab::Routing.url_helpers.active_common_namespace_project_prometheus_metrics_url('foo', 'bar', :json) + subject { described_class.regex } - expect(described_class.regex).not_to match url - end + it_behaves_like 'a regex which matches the expected url' + it_behaves_like 'does not match non-matching urls' + end - it 'does not match other gitlab urls' do - url = Gitlab.config.gitlab.url + describe '#grafana_regex' do + let(:url) do + Gitlab::Routing.url_helpers.namespace_project_grafana_api_metrics_dashboard_url( + 'foo', + 'bar', + start: '2019-08-02T05:43:09.000Z', + dashboard: 'config/prometheus/common_metrics.yml', + group: 'awesome group', + anchor: 'title' + ) + end - expect(described_class.regex).not_to match url + let(:expected_params) do + { + 'url' => url, + 'namespace' => 'foo', + 'project' => 'bar', + 'query' => '?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z', + 'anchor' => '#title' + } end - it 'does not match non-gitlab urls' do - url = 'https://www.super_awesome_site.com/' + subject { described_class.grafana_regex } - expect(described_class.regex).not_to match url - end + it_behaves_like 'a regex which matches the expected url' + it_behaves_like 'does not match non-matching urls' end describe '#build_dashboard_url' do diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 297367853f0..e1622888d79 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -57,14 +57,14 @@ RSpec.describe Release do subject { release.assets_count } it 'returns the number of sources' do - is_expected.to eq(Releases::Source::FORMATS.count) + is_expected.to eq(Gitlab::Workhorse::ARCHIVE_FORMATS.count) end context 'when a links exists' do let!(:link) { create(:release_link, release: release) } it 'counts the link as an asset' do - is_expected.to eq(1 + Releases::Source::FORMATS.count) + is_expected.to eq(1 + Gitlab::Workhorse::ARCHIVE_FORMATS.count) end it "excludes sources count when asked" do diff --git a/spec/models/releases/source_spec.rb b/spec/models/releases/source_spec.rb index c5213196962..c8ac8e31c97 100644 --- a/spec/models/releases/source_spec.rb +++ b/spec/models/releases/source_spec.rb @@ -11,7 +11,7 @@ describe Releases::Source do it 'returns all formats of sources' do expect(subject.map(&:format)) - .to match_array(described_class::FORMATS) + .to match_array(Gitlab::Workhorse::ARCHIVE_FORMATS) end end diff --git a/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb b/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb index 920fcbde483..21c32c9c04a 100644 --- a/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb +++ b/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true shared_examples 'archive download buttons' do - let(:formats) { %w(zip tar.gz tar.bz2 tar) } let(:path_to_visit) { project_path(project) } let(:ref) { project.default_branch } @@ -13,7 +12,7 @@ shared_examples 'archive download buttons' do context 'private project' do it 'shows archive download buttons with external storage URL prepended and user token appended to their href' do - formats.each do |format| + Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format| path = archive_path(project, ref, format) uri = URI('https://cdn.gitlab.com') uri.path = path @@ -28,7 +27,7 @@ shared_examples 'archive download buttons' do let(:project) { create(:project, :repository, :public) } it 'shows archive download buttons with external storage URL prepended to their href' do - formats.each do |format| + Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format| path = archive_path(project, ref, format) uri = URI('https://cdn.gitlab.com') uri.path = path @@ -45,7 +44,7 @@ shared_examples 'archive download buttons' do end it 'shows default archive download buttons' do - formats.each do |format| + Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format| path = archive_path(project, ref, format) expect(page).to have_link format, href: path |