summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-19 00:09:15 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-19 00:09:15 +0000
commit60f63d15794e62c4bac9756445f618cd9acb8654 (patch)
tree30c2b2dc678995dd332b32672f9faa460fabdb79 /spec
parent93d7441cc98c1db55797a2181a3d9f4b3d26d82c (diff)
downloadgitlab-ce-60f63d15794e62c4bac9756445f618cd9acb8654.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/graphql/types/board_type_spec.rb15
-rw-r--r--spec/graphql/types/group_type_spec.rb10
-rw-r--r--spec/graphql/types/project_type_spec.rb7
-rw-r--r--spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb26
-rw-r--r--spec/lib/banzai/filter/inline_metrics_filter_spec.rb79
-rw-r--r--spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb27
-rw-r--r--spec/requests/api/graphql/boards/boards_query_spec.rb27
-rw-r--r--spec/services/incident_management/create_issue_service_spec.rb13
-rw-r--r--spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb36
-rw-r--r--spec/support/shared_examples/banzai/filters/inline_embeds_shared_examples.rb48
-rw-r--r--spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb92
12 files changed, 297 insertions, 111 deletions
diff --git a/spec/graphql/types/board_type_spec.rb b/spec/graphql/types/board_type_spec.rb
new file mode 100644
index 00000000000..9d18065bbcd
--- /dev/null
+++ b/spec/graphql/types/board_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['Board'] do
+ it { expect(described_class.graphql_name).to eq('Board') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_board) }
+
+ it 'has specific fields' do
+ expected_fields = %w[id name]
+
+ is_expected.to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 6a0028f6529..240dd9fa5e2 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -16,9 +16,17 @@ describe GitlabSchema.types['Group'] do
web_url avatar_url share_with_group_lock project_creation_level
subgroup_creation_level require_two_factor_authentication
two_factor_grace_period auto_devops_enabled emails_disabled
- mentions_disabled parent
+ mentions_disabled parent boards
]
is_expected.to include_graphql_fields(*expected_fields)
end
+
+ describe 'boards field' do
+ subject { described_class.fields['boards'] }
+
+ it 'returns boards' do
+ is_expected.to have_graphql_type(Types::BoardType.connection_type)
+ end
+ end
end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index ac2d2d6f7f0..9c6d1e3f35c 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -24,6 +24,7 @@ describe GitlabSchema.types['Project'] do
namespace group statistics repository merge_requests merge_request issues
issue pipelines removeSourceBranchAfterMerge sentryDetailedError snippets
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
+ boards
]
is_expected.to include_graphql_fields(*expected_fields)
@@ -77,4 +78,10 @@ describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::EnvironmentType.connection_type) }
it { is_expected.to have_graphql_resolver(Resolvers::EnvironmentsResolver) }
end
+
+ describe 'boards field' do
+ subject { described_class.fields['boards'] }
+
+ it { is_expected.to have_graphql_type(Types::BoardType.connection_type) }
+ end
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
index fd6f8816b63..9ac06a90efd 100644
--- a/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb
@@ -8,40 +8,26 @@ describe Banzai::Filter::InlineGrafanaMetricsFilter do
let_it_be(:project) { create(:project) }
let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
- let(:input) { %(<a href="#{url}">example</a>) }
+ let(:input) { %(<a href="#{trigger_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
- 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(
+ let(:trigger_url) { grafana_integration.grafana_url + dashboard_path }
+ let(:dashboard_url) do
+ urls.project_grafana_api_metrics_dashboard_url(
project,
embedded: true,
- grafana_url: url,
+ grafana_url: trigger_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
+ it_behaves_like 'a metrics embed filter'
context 'when grafana is not configured' do
before do
diff --git a/spec/lib/banzai/filter/inline_metrics_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
index 66bbcbf7292..1546a5e88ed 100644
--- a/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
@@ -5,66 +5,31 @@ require 'spec_helper'
describe Banzai::Filter::InlineMetricsFilter do
include FilterSpecHelper
- let(:input) { %(<a href="#{url}">example</a>) }
- let(:doc) { filter(input) }
-
- context 'when the document has an external link' do
- let(:url) { 'https://foo.com' }
-
- it 'leaves regular non-metrics links unchanged' do
- expect(doc.to_s).to eq(input)
- end
- end
-
- context 'when the document has a metrics dashboard link' do
- let(:params) { ['foo', 'bar', 12] }
- let(:url) { urls.metrics_namespace_project_environment_url(*params) }
-
- it 'leaves the original link unchanged' do
- expect(doc.at_css('a').to_s).to eq(input)
- 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.metrics_dashboard_namespace_project_environment_url(*params, embedded: true)
- expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url)
+ let(:params) { ['foo', 'bar', 12] }
+ let(:query_params) { {} }
+
+ let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, query_params) }
+ let(:dashboard_url) { urls.metrics_dashboard_namespace_project_environment_url(*params, **query_params, embedded: true) }
+
+ it_behaves_like 'a metrics embed filter'
+
+ context 'with query params specified' do
+ let(:query_params) do
+ {
+ dashboard: 'config/prometheus/common_metrics.yml',
+ group: 'System metrics (Kubernetes)',
+ title: 'Core Usage (Pod Average)',
+ y_label: 'Cores per Pod'
+ }
end
- context 'when the metrics 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(doc.at_css('p').to_s).to include(paragraph)
- expect(doc.at_css('.js-render-metrics')).to be_present
- end
- end
-
- context 'with dashboard params specified' do
- let(:params) do
- [
- 'foo',
- 'bar',
- 12,
- {
- embedded: true,
- dashboard: 'config/prometheus/common_metrics.yml',
- group: 'System metrics (Kubernetes)',
- title: 'Core Usage (Pod Average)',
- y_label: 'Cores per Pod'
- }
- ]
- end
+ it_behaves_like 'a metrics embed filter'
+ 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
+ it 'leaves links to other dashboards unchanged' do
+ url = urls.namespace_project_grafana_api_metrics_dashboard_url('foo', 'bar')
+ input = %(<a href="#{url}">example</a>)
- dashboard_url = urls.metrics_dashboard_namespace_project_environment_url(*params)
- expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url)
- end
- end
+ expect(filter(input).to_s).to eq(input)
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 e2615ea5069..f91927412cb 100644
--- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
@@ -18,33 +18,6 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do
end
context 'with a metrics charts placeholder' do
- 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 '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
-
- context 'the user has requisite permissions' do
- let(:user) { create(:user) }
- let(:doc) { filter(input, current_user: user) }
-
- it 'leaves the placeholder' do
- project.add_maintainer(user)
-
- expect(doc.to_s).to eq input
- end
- end
- end
-
let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) }
it_behaves_like 'a supported metrics dashboard url'
diff --git a/spec/requests/api/graphql/boards/boards_query_spec.rb b/spec/requests/api/graphql/boards/boards_query_spec.rb
new file mode 100644
index 00000000000..d0a2d0fffaf
--- /dev/null
+++ b/spec/requests/api/graphql/boards/boards_query_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'get list of boards' do
+ include GraphqlHelpers
+
+ include_context 'group and project boards query context'
+
+ describe 'for a project' do
+ let(:board_parent) { create(:project, :repository, :private) }
+ let(:boards_data) { graphql_data['project']['boards']['edges'] }
+
+ it_behaves_like 'group and project boards query'
+ end
+
+ describe 'for a group' do
+ let(:board_parent) { create(:group, :private) }
+ let(:boards_data) { graphql_data['group']['boards']['edges'] }
+
+ before do
+ allow(board_parent).to receive(:multiple_issue_boards_available?).and_return(false)
+ end
+
+ it_behaves_like 'group and project boards query'
+ end
+end
diff --git a/spec/services/incident_management/create_issue_service_spec.rb b/spec/services/incident_management/create_issue_service_spec.rb
index e720aafb897..4c7fb682193 100644
--- a/spec/services/incident_management/create_issue_service_spec.rb
+++ b/spec/services/incident_management/create_issue_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe IncidentManagement::CreateIssueService do
let(:project) { create(:project, :repository, :private) }
- let(:user) { User.alert_bot }
+ let_it_be(:user) { User.alert_bot }
let(:service) { described_class.new(project, alert_payload) }
let(:alert_starts_at) { Time.now }
let(:alert_title) { 'TITLE' }
@@ -29,7 +29,6 @@ describe IncidentManagement::CreateIssueService do
context 'when create_issue enabled' do
let(:issue) { subject[:issue] }
- let(:summary_separator) { "\n---\n\n" }
before do
setting.update!(create_issue: true)
@@ -42,7 +41,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.author).to eq(user)
expect(issue.title).to eq(alert_title)
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
- expect(separator_count(issue.description)).to eq 0
+ expect(separator_count(issue.description)).to eq(0)
end
end
@@ -74,7 +73,7 @@ describe IncidentManagement::CreateIssueService do
expect(subject).to include(status: :success)
expect(issue.description).to include(alert_presenter.issue_summary_markdown)
- expect(separator_count(issue.description)).to eq 1
+ expect(separator_count(issue.description)).to eq(1)
expect(issue.description).to include(template_content)
end
end
@@ -134,7 +133,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).to include(template_content)
expect(issue.description).to include(alt_template)
- expect(separator_count(issue.description)).to eq 2
+ expect(separator_count(issue.description)).to eq(2)
end
end
@@ -171,7 +170,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.title).to include(query_title)
expect(issue.title).to include('for 5 minutes')
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
- expect(separator_count(issue.description)).to eq 0
+ expect(separator_count(issue.description)).to eq(0)
end
end
@@ -306,6 +305,8 @@ describe IncidentManagement::CreateIssueService do
end
def separator_count(text)
+ summary_separator = "\n\n---\n\n"
+
text.scan(summary_separator).size
end
end
diff --git a/spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb b/spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb
new file mode 100644
index 00000000000..e744c3d0abb
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'group and project boards query context' do
+ let_it_be(:user) { create :user }
+ let(:current_user) { user }
+ let(:params) { '' }
+ let(:board_parent_type) { board_parent.class.to_s.downcase }
+ let(:start_cursor) { graphql_data[board_parent_type]['boards']['pageInfo']['startCursor'] }
+ let(:end_cursor) { graphql_data[board_parent_type]['boards']['pageInfo']['endCursor'] }
+
+ def query(board_params = params)
+ graphql_query_for(
+ board_parent_type,
+ { 'fullPath' => board_parent.full_path },
+ <<~BOARDS
+ boards(#{board_params}) {
+ pageInfo {
+ startCursor
+ endCursor
+ }
+ edges {
+ node {
+ #{all_graphql_fields_for('boards'.classify)}
+ }
+ }
+ }
+ BOARDS
+ )
+ end
+
+ def grab_names(data = boards_data)
+ data.map do |board|
+ board.dig('node', 'name')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/banzai/filters/inline_embeds_shared_examples.rb b/spec/support/shared_examples/banzai/filters/inline_embeds_shared_examples.rb
new file mode 100644
index 00000000000..599161abbfe
--- /dev/null
+++ b/spec/support/shared_examples/banzai/filters/inline_embeds_shared_examples.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+# Expects 2 attributes to be defined:
+# trigger_url - Url expected to trigger the insertion of a placeholder.
+# dashboard_url - Url expected to be present in the placeholder.
+RSpec.shared_examples 'a metrics embed filter' do
+ let(:input) { %(<a href="#{url}">example</a>) }
+ let(:doc) { filter(input) }
+
+ context 'when the document has an external link' do
+ let(:url) { 'https://foo.com' }
+
+ it 'leaves regular non-metrics links unchanged' do
+ expect(doc.to_s).to eq(input)
+ end
+ end
+
+ context 'when the document contains an embeddable link' do
+ let(:url) { trigger_url }
+
+ it 'leaves the original link unchanged' do
+ expect(unescape(doc.at_css('a').to_s)).to eq(input)
+ end
+
+ it 'appends a metrics charts placeholder' do
+ node = doc.at_css('.js-render-metrics')
+ expect(node).to be_present
+
+ expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url)
+ end
+
+ context 'in a paragraph' do
+ let(:paragraph) { %(This is an <a href="#{url}">example</a> of metrics.) }
+ let(:input) { %(<p>#{paragraph}</p>) }
+
+ it 'appends a metrics 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
+ end
+
+ # Nokogiri escapes the URLs, but we don't care about that
+ # distinction for the purposes of these filters
+ def unescape(html)
+ CGI.unescapeHTML(html)
+ end
+end
diff --git a/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb b/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb
new file mode 100644
index 00000000000..d283b3a3b27
--- /dev/null
+++ b/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples '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 '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
+
+ context 'the user has requisite permissions' do
+ let(:user) { create(:user) }
+ let(:doc) { filter(input, current_user: user) }
+
+ it 'leaves the placeholder' do
+ project.add_maintainer(user)
+
+ expect(doc.to_s).to eq(input)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
new file mode 100644
index 00000000000..6044fefd2f7
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'group and project boards query' do
+ include GraphqlHelpers
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ context 'when the user does not have access to the board parent' do
+ it 'returns nil' do
+ create(:board, resource_parent: board_parent, name: 'A')
+
+ post_graphql(query)
+
+ expect(graphql_data[board_parent_type]).to be_nil
+ end
+ end
+
+ context 'when no permission to read board' do
+ it 'does not return any boards' do
+ board_parent.add_guest(current_user)
+ board = create(:board, resource_parent: board_parent, name: 'A')
+
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :read_board, board).and_return(false)
+
+ post_graphql(query, current_user: current_user)
+
+ expect(boards_data).to be_empty
+ end
+ end
+
+ context 'when user can read the board parent' do
+ before do
+ board_parent.add_reporter(current_user)
+ end
+
+ it 'does not create a default board' do
+ post_graphql(query, current_user: current_user)
+
+ expect(boards_data).to be_empty
+ end
+
+ describe 'sorting and pagination' do
+ context 'when using default sorting' do
+ let!(:board_B) { create(:board, resource_parent: board_parent, name: 'B') }
+ let!(:board_C) { create(:board, resource_parent: board_parent, name: 'C') }
+ let!(:board_a) { create(:board, resource_parent: board_parent, name: 'a') }
+ let!(:board_A) { create(:board, resource_parent: board_parent, name: 'A') }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ context 'when ascending' do
+ let(:boards) { [board_a, board_A, board_B, board_C] }
+ let(:expected_boards) do
+ if board_parent.multiple_issue_boards_available?
+ boards
+ else
+ [boards.first]
+ end
+ end
+
+ it 'sorts boards' do
+ expect(grab_names).to eq expected_boards.map(&:name)
+ end
+
+ context 'when paginating' do
+ let(:params) { 'first: 2' }
+
+ it 'sorts boards' do
+ expect(grab_names).to eq expected_boards.first(2).map(&:name)
+
+ cursored_query = query("after: \"#{end_cursor}\"")
+ post_graphql(cursored_query, current_user: current_user)
+
+ response_data = JSON.parse(response.body)['data'][board_parent_type]['boards']['edges']
+
+ expect(grab_names(response_data)).to eq expected_boards.drop(2).first(2).map(&:name)
+ end
+ end
+ end
+ end
+ end
+ end
+end