...@@ -5,66 +5,31 @@ require 'spec_helper' ...@@ -5,66 +5,31 @@ require 'spec_helper'
describe Banzai::Filter::InlineMetricsFilter do describe Banzai::Filter::InlineMetricsFilter do
include FilterSpecHelper 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(:params) { ['foo', 'bar', 12] }
let(:url) { urls.metrics_namespace_project_environment_url(*params) } let(:query_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) let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, query_params) }
expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url) let(:dashboard_url) { urls.metrics_dashboard_namespace_project_environment_url(*params, **query_params, embedded: true) }
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 it_behaves_like 'a metrics embed filter'
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 context 'with query params specified' do
let(:params) do let(:query_params) do
[
'foo',
'bar',
12,
{ {
embedded: true,
dashboard: 'config/prometheus/common_metrics.yml', dashboard: 'config/prometheus/common_metrics.yml',
group: 'System metrics (Kubernetes)', group: 'System metrics (Kubernetes)',
title: 'Core Usage (Pod Average)', title: 'Core Usage (Pod Average)',
y_label: 'Cores per Pod' y_label: 'Cores per Pod'
} }
]
end end
it 'appends a metrics charts placeholder with dashboard url after metrics links' do it_behaves_like 'a metrics embed filter'
node = doc.at_css('.js-render-metrics')
expect(node).to be_present
dashboard_url = urls.metrics_dashboard_namespace_project_environment_url(*params)
expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url)
end
end end
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>)
expect(filter(input).to_s).to eq(input)
end end
end end
...@@ -18,33 +18,6 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do ...@@ -18,33 +18,6 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do
end end
context 'with a metrics charts placeholder' do 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>) } let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) }
it_behaves_like 'a supported metrics dashboard url' it_behaves_like 'a supported metrics dashboard url'
... ...
......
# 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
...@@ -4,7 +4,7 @@ require 'spec_helper' ...@@ -4,7 +4,7 @@ require 'spec_helper'
describe IncidentManagement::CreateIssueService do describe IncidentManagement::CreateIssueService do
let(:project) { create(:project, :repository, :private) } 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(:service) { described_class.new(project, alert_payload) }
let(:alert_starts_at) { Time.now } let(:alert_starts_at) { Time.now }
let(:alert_title) { 'TITLE' } let(:alert_title) { 'TITLE' }
...@@ -29,7 +29,6 @@ describe IncidentManagement::CreateIssueService do ...@@ -29,7 +29,6 @@ describe IncidentManagement::CreateIssueService do
context 'when create_issue enabled' do context 'when create_issue enabled' do
let(:issue) { subject[:issue] } let(:issue) { subject[:issue] }
let(:summary_separator) { "\n---\n\n" }
before do before do
setting.update!(create_issue: true) setting.update!(create_issue: true)
...@@ -42,7 +41,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -42,7 +41,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.author).to eq(user) expect(issue.author).to eq(user)
expect(issue.title).to eq(alert_title) expect(issue.title).to eq(alert_title)
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip) 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
end end
...@@ -74,7 +73,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -74,7 +73,7 @@ describe IncidentManagement::CreateIssueService do
expect(subject).to include(status: :success) expect(subject).to include(status: :success)
expect(issue.description).to include(alert_presenter.issue_summary_markdown) 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) expect(issue.description).to include(template_content)
end end
end end
...@@ -134,7 +133,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -134,7 +133,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.description).to include(alert_presenter.issue_summary_markdown) expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).to include(template_content) expect(issue.description).to include(template_content)
expect(issue.description).to include(alt_template) 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
end end
...@@ -171,7 +170,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -171,7 +170,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.title).to include(query_title) expect(issue.title).to include(query_title)
expect(issue.title).to include('for 5 minutes') expect(issue.title).to include('for 5 minutes')
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip) 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
end end
...@@ -306,6 +305,8 @@ describe IncidentManagement::CreateIssueService do ...@@ -306,6 +305,8 @@ describe IncidentManagement::CreateIssueService do
end end
def separator_count(text) def separator_count(text)
summary_separator = "\n\n---\n\n"
text.scan(summary_separator).size text.scan(summary_separator).size
end end
end end
# 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
# 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
# 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
# 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