Commit 0637ba1e authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 4720b569
...@@ -42,6 +42,7 @@ module Ci ...@@ -42,6 +42,7 @@ module Ci
metrics: :gzip, metrics: :gzip,
metrics_referee: :gzip, metrics_referee: :gzip,
network_referee: :gzip, network_referee: :gzip,
lsif: :gzip,
# All these file formats use `raw` as we need to store them uncompressed # All these file formats use `raw` as we need to store them uncompressed
# for Frontend to fetch the files and do analysis # for Frontend to fetch the files and do analysis
...@@ -53,8 +54,7 @@ module Ci ...@@ -53,8 +54,7 @@ module Ci
dast: :raw, dast: :raw,
license_management: :raw, license_management: :raw,
license_scanning: :raw, license_scanning: :raw,
performance: :raw, performance: :raw
lsif: :raw
}.freeze }.freeze
TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze
......
...@@ -128,12 +128,12 @@ class Issue < ApplicationRecord ...@@ -128,12 +128,12 @@ class Issue < ApplicationRecord
def self.reference_pattern def self.reference_pattern
@reference_pattern ||= %r{ @reference_pattern ||= %r{
(#{Project.reference_pattern})? (#{Project.reference_pattern})?
#{Regexp.escape(reference_prefix)}(?<issue>\d+) #{Regexp.escape(reference_prefix)}#{Gitlab::Regex.issue}
}x }x
end end
def self.link_reference_pattern def self.link_reference_pattern
@link_reference_pattern ||= super("issues", /(?<issue>\d+)/) @link_reference_pattern ||= super("issues", Gitlab::Regex.issue)
end end
def self.reference_valid?(reference) def self.reference_valid?(reference)
......
...@@ -48,6 +48,7 @@ class MergeRequest < ApplicationRecord ...@@ -48,6 +48,7 @@ class MergeRequest < ApplicationRecord
# 1. There are arguments - in which case we might be trying to force-reload. # 1. There are arguments - in which case we might be trying to force-reload.
# 2. This association is already loaded. # 2. This association is already loaded.
# 3. The latest diff does not exist. # 3. The latest diff does not exist.
# 4. It doesn't have any merge_request_diffs - it returns an empty MergeRequestDiff
# #
# The second one in particular is important - MergeRequestDiff#merge_request # The second one in particular is important - MergeRequestDiff#merge_request
# is the inverse of MergeRequest#merge_request_diff, which means it may not be # is the inverse of MergeRequest#merge_request_diff, which means it may not be
...@@ -56,7 +57,7 @@ class MergeRequest < ApplicationRecord ...@@ -56,7 +57,7 @@ class MergeRequest < ApplicationRecord
def merge_request_diff def merge_request_diff
fallback = latest_merge_request_diff unless association(:merge_request_diff).loaded? fallback = latest_merge_request_diff unless association(:merge_request_diff).loaded?
fallback || super fallback || super || MergeRequestDiff.new(merge_request_id: id)
end end
belongs_to :head_pipeline, foreign_key: "head_pipeline_id", class_name: "Ci::Pipeline" belongs_to :head_pipeline, foreign_key: "head_pipeline_id", class_name: "Ci::Pipeline"
...@@ -404,7 +405,7 @@ class MergeRequest < ApplicationRecord ...@@ -404,7 +405,7 @@ class MergeRequest < ApplicationRecord
end end
def commits(limit: nil) def commits(limit: nil)
return merge_request_diff.commits(limit: limit) if persisted? return merge_request_diff.commits(limit: limit) if merge_request_diff.persisted?
commits_arr = if compare_commits commits_arr = if compare_commits
reversed_commits = compare_commits.reverse reversed_commits = compare_commits.reverse
...@@ -421,7 +422,7 @@ class MergeRequest < ApplicationRecord ...@@ -421,7 +422,7 @@ class MergeRequest < ApplicationRecord
end end
def commits_count def commits_count
if persisted? if merge_request_diff.persisted?
merge_request_diff.commits_count merge_request_diff.commits_count
elsif compare_commits elsif compare_commits
compare_commits.size compare_commits.size
...@@ -431,7 +432,7 @@ class MergeRequest < ApplicationRecord ...@@ -431,7 +432,7 @@ class MergeRequest < ApplicationRecord
end end
def commit_shas(limit: nil) def commit_shas(limit: nil)
return merge_request_diff.commit_shas(limit: limit) if persisted? return merge_request_diff.commit_shas(limit: limit) if merge_request_diff.persisted?
shas = shas =
if compare_commits if compare_commits
...@@ -492,11 +493,11 @@ class MergeRequest < ApplicationRecord ...@@ -492,11 +493,11 @@ class MergeRequest < ApplicationRecord
end end
def first_commit def first_commit
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first compare_commits.present? ? compare_commits.first : merge_request_diff.first_commit
end end
def raw_diffs(*args) def raw_diffs(*args)
merge_request_diff ? merge_request_diff.raw_diffs(*args) : compare.raw_diffs(*args) compare.present? ? compare.raw_diffs(*args) : merge_request_diff.raw_diffs(*args)
end end
def diffs(diff_options = {}) def diffs(diff_options = {})
...@@ -557,7 +558,7 @@ class MergeRequest < ApplicationRecord ...@@ -557,7 +558,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_base_commit def diff_base_commit
if persisted? if merge_request_diff.persisted?
merge_request_diff.base_commit merge_request_diff.base_commit
else else
branch_merge_base_commit branch_merge_base_commit
...@@ -565,7 +566,7 @@ class MergeRequest < ApplicationRecord ...@@ -565,7 +566,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_start_commit def diff_start_commit
if persisted? if merge_request_diff.persisted?
merge_request_diff.start_commit merge_request_diff.start_commit
else else
target_branch_head target_branch_head
...@@ -573,7 +574,7 @@ class MergeRequest < ApplicationRecord ...@@ -573,7 +574,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_head_commit def diff_head_commit
if persisted? if merge_request_diff.persisted?
merge_request_diff.head_commit merge_request_diff.head_commit
else else
source_branch_head source_branch_head
...@@ -581,7 +582,7 @@ class MergeRequest < ApplicationRecord ...@@ -581,7 +582,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_start_sha def diff_start_sha
if persisted? if merge_request_diff.persisted?
merge_request_diff.start_commit_sha merge_request_diff.start_commit_sha
else else
target_branch_head.try(:sha) target_branch_head.try(:sha)
...@@ -589,7 +590,7 @@ class MergeRequest < ApplicationRecord ...@@ -589,7 +590,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_base_sha def diff_base_sha
if persisted? if merge_request_diff.persisted?
merge_request_diff.base_commit_sha merge_request_diff.base_commit_sha
else else
branch_merge_base_commit.try(:sha) branch_merge_base_commit.try(:sha)
...@@ -597,7 +598,7 @@ class MergeRequest < ApplicationRecord ...@@ -597,7 +598,7 @@ class MergeRequest < ApplicationRecord
end end
def diff_head_sha def diff_head_sha
if persisted? if merge_request_diff.persisted?
merge_request_diff.head_commit_sha merge_request_diff.head_commit_sha
else else
source_branch_head.try(:sha) source_branch_head.try(:sha)
...@@ -758,7 +759,7 @@ class MergeRequest < ApplicationRecord ...@@ -758,7 +759,7 @@ class MergeRequest < ApplicationRecord
end end
def ensure_merge_request_diff def ensure_merge_request_diff
merge_request_diff || create_merge_request_diff merge_request_diff.persisted? || create_merge_request_diff
end end
def create_merge_request_diff def create_merge_request_diff
...@@ -1005,7 +1006,7 @@ class MergeRequest < ApplicationRecord ...@@ -1005,7 +1006,7 @@ class MergeRequest < ApplicationRecord
def closes_issues(current_user = self.author) def closes_issues(current_user = self.author)
if target_branch == project.default_branch if target_branch == project.default_branch
messages = [title, description] messages = [title, description]
messages.concat(commits.map(&:safe_message)) if merge_request_diff messages.concat(commits.map(&:safe_message)) if merge_request_diff.persisted?
Gitlab::ClosingIssueExtractor.new(project, current_user) Gitlab::ClosingIssueExtractor.new(project, current_user)
.closed_by_message(messages.join("\n")) .closed_by_message(messages.join("\n"))
...@@ -1421,7 +1422,7 @@ class MergeRequest < ApplicationRecord ...@@ -1421,7 +1422,7 @@ class MergeRequest < ApplicationRecord
end end
def has_commits? def has_commits?
merge_request_diff && commits_count.to_i > 0 merge_request_diff.persisted? && commits_count.to_i > 0
end end
def has_no_commits? def has_no_commits?
......
...@@ -19,9 +19,9 @@ class IssueTrackerService < Service ...@@ -19,9 +19,9 @@ class IssueTrackerService < Service
# overridden patterns. See ReferenceRegexes.external_pattern # overridden patterns. See ReferenceRegexes.external_pattern
def self.reference_pattern(only_long: false) def self.reference_pattern(only_long: false)
if only_long if only_long
/(\b[A-Z][A-Z0-9_]*-)(?<issue>\d+)/ /(\b[A-Z][A-Z0-9_]*-)#{Gitlab::Regex.issue}/
else else
/(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})(?<issue>\d+)/ /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})#{Gitlab::Regex.issue}/
end end
end end
......
...@@ -8,7 +8,7 @@ class YoutrackService < IssueTrackerService ...@@ -8,7 +8,7 @@ class YoutrackService < IssueTrackerService
if only_long if only_long
/(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/
else else
/(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}(?<issue>\d+))/ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}#{Gitlab::Regex.issue})/
end end
end end
......
---
title: Drop signatures in email replies
merge_request: 25389
author: Diego Louzán
type: changed
---
title: Upgrade pages to 1.16.0
merge_request: 25238
author:
type: added
...@@ -87,6 +87,7 @@ For instance `RETRIES=1 bin/rspec ...` would retry the failing examples once. ...@@ -87,6 +87,7 @@ For instance `RETRIES=1 bin/rspec ...` would retry the failing examples once.
- [Dropdowns rendering upward or downward due to window size and scroll position](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17660) - [Dropdowns rendering upward or downward due to window size and scroll position](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17660)
- [Lazy loaded images can cause Capybara to misclick](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18713) - [Lazy loaded images can cause Capybara to misclick](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18713)
- [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18742) - [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18742)
- [Wait for the image to be lazy-loaded when asserting on a Markdown image's src attribute](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25408)
#### Capybara viewport size related issues #### Capybara viewport size related issues
......
...@@ -12,7 +12,7 @@ module Gitlab ...@@ -12,7 +12,7 @@ module Gitlab
def execute(upload_parent:, uploader_class:) def execute(upload_parent:, uploader_class:)
attachments = [] attachments = []
message.attachments.each do |attachment| filter_signature_attachments(message).each do |attachment|
tmp = Tempfile.new("gitlab-email-attachment") tmp = Tempfile.new("gitlab-email-attachment")
begin begin
File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded } File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded }
...@@ -32,6 +32,22 @@ module Gitlab ...@@ -32,6 +32,22 @@ module Gitlab
attachments attachments
end end
private
# If this is a signed message (e.g. S/MIME or PGP), remove the signature
# from the uploaded attachments
def filter_signature_attachments(message)
attachments = message.attachments
if message.content_type&.starts_with?('multipart/signed')
signature_protocol = message.content_type_parameters[:protocol]
attachments.delete_if { |attachment| attachment.content_type.starts_with?(signature_protocol) } if signature_protocol.present?
end
attachments
end
end end
end end
end end
...@@ -112,7 +112,7 @@ module Gitlab ...@@ -112,7 +112,7 @@ module Gitlab
# Based on Jira's project key format # Based on Jira's project key format
# https://confluence.atlassian.com/adminjiraserver073/changing-the-project-key-format-861253229.html # https://confluence.atlassian.com/adminjiraserver073/changing-the-project-key-format-861253229.html
def jira_issue_key_regex def jira_issue_key_regex
@jira_issue_key_regex ||= /[A-Z][A-Z_0-9]+-\d+/ @jira_issue_key_regex ||= /[A-Z][A-Z_0-9]+-\d+\b/
end end
def jira_transition_id_regex def jira_transition_id_regex
...@@ -144,6 +144,10 @@ module Gitlab ...@@ -144,6 +144,10 @@ module Gitlab
def utc_date_regex def utc_date_regex
@utc_date_regex ||= /\A[0-9]{4}-[0-9]{2}-[0-9]{2}\z/.freeze @utc_date_regex ||= /\A[0-9]{4}-[0-9]{2}-[0-9]{2}\z/.freeze
end end
def issue
@issue ||= /(?<issue>\d+\b)/
end
end end
end end
......
...@@ -77,6 +77,18 @@ describe Projects::MergeRequestsController do ...@@ -77,6 +77,18 @@ describe Projects::MergeRequestsController do
end end
end end
context 'when diff is missing' do
render_views
it 'renders merge request page' do
merge_request.merge_request_diff.destroy
go(format: :html)
expect(response).to be_successful
end
end
it "renders merge request page" do it "renders merge request page" do
expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
......
...@@ -141,11 +141,11 @@ FactoryBot.define do ...@@ -141,11 +141,11 @@ FactoryBot.define do
trait :lsif do trait :lsif do
file_type { :lsif } file_type { :lsif }
file_format { :raw } file_format { :gzip }
after(:build) do |artifact, evaluator| after(:build) do |artifact, evaluator|
artifact.file = fixture_file_upload( artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/lsif.json.gz'), 'application/octet-stream') Rails.root.join('spec/fixtures/lsif.json.gz'), 'application/x-gzip')
end end
end end
......
...@@ -53,7 +53,7 @@ describe 'User creates snippet', :js do ...@@ -53,7 +53,7 @@ describe 'User creates snippet', :js do
page.within('#new_personal_snippet .md-preview-holder') do page.within('#new_personal_snippet .md-preview-holder') do
expect(page).to have_content('My Snippet') expect(page).to have_content('My Snippet')
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/user/#{user.id}/\h{32}/banana_sample\.gif\z}) expect(link).to match(%r{/uploads/-/system/user/#{user.id}/\h{32}/banana_sample\.gif\z})
# Adds a cache buster for checking if the image exists as Selenium is now handling the cached regquests # Adds a cache buster for checking if the image exists as Selenium is now handling the cached regquests
...@@ -73,7 +73,7 @@ describe 'User creates snippet', :js do ...@@ -73,7 +73,7 @@ describe 'User creates snippet', :js do
click_button('Create snippet') click_button('Create snippet')
wait_for_requests wait_for_requests
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z}) expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") } reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") }
...@@ -98,7 +98,7 @@ describe 'User creates snippet', :js do ...@@ -98,7 +98,7 @@ describe 'User creates snippet', :js do
expect(page).to have_selector('strong') expect(page).to have_selector('strong')
end end
expect(page).to have_content('Hello World!') expect(page).to have_content('Hello World!')
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z}) expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") } reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") }
......
# Do not mangle line endings or signature will be invalid
valid_reply_signed_smime.eml eol=crlf
\ No newline at end of file
This diff is collapsed.
...@@ -16,5 +16,20 @@ describe Gitlab::Email::AttachmentUploader do ...@@ -16,5 +16,20 @@ describe Gitlab::Email::AttachmentUploader do
expect(link[:alt]).to eq("bricks") expect(link[:alt]).to eq("bricks")
expect(link[:url]).to include("bricks.png") expect(link[:url]).to include("bricks.png")
end end
context 'with a signed message' do
let(:message_raw) { fixture_file("emails/valid_reply_signed_smime.eml") }
it 'uploads all attachments except the signature' do
links = described_class.new(message).execute(upload_parent: project, uploader_class: FileUploader)
expect(links).not_to include(a_hash_including(alt: 'smime.p7s'))
image_link = links.first
expect(image_link).not_to be_nil
expect(image_link[:alt]).to eq('gitlab_logo')
expect(image_link[:url]).to include('gitlab_logo.png')
end
end
end end
end end
...@@ -3,17 +3,23 @@ ...@@ -3,17 +3,23 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::Email::Handler do describe Gitlab::Email::Handler do
let(:email) { Mail.new { body 'email' } }
describe '.for' do describe '.for' do
it 'picks issue handler if there is no merge request prefix' do it 'picks issue handler if there is no merge request prefix' do
expect(described_class.for('email', 'project+key')).to be_an_instance_of(Gitlab::Email::Handler::CreateIssueHandler) expect(described_class.for(email, 'project+key')).to be_an_instance_of(Gitlab::Email::Handler::CreateIssueHandler)
end end
it 'picks merge request handler if there is merge request key' do it 'picks merge request handler if there is merge request key' do
expect(described_class.for('email', 'project+merge-request+key')).to be_an_instance_of(Gitlab::Email::Handler::CreateMergeRequestHandler) expect(described_class.for(email, 'project+merge-request+key')).to be_an_instance_of(Gitlab::Email::Handler::CreateMergeRequestHandler)
end end
it 'returns nil if no handler is found' do it 'returns nil if no handler is found' do
expect(described_class.for('email', '')).to be_nil expect(described_class.for(email, '')).to be_nil
end
it 'returns nil if provided email is nil' do
expect(described_class.for(nil, '')).to be_nil
end end
end end
...@@ -25,7 +31,7 @@ describe Gitlab::Email::Handler do ...@@ -25,7 +31,7 @@ describe Gitlab::Email::Handler do
it 'picks each handler at least once' do it 'picks each handler at least once' do
matched_handlers = addresses.map do |address| matched_handlers = addresses.map do |address|
described_class.for('email', address).class described_class.for(email, address).class
end end
expect(matched_handlers.uniq).to match_array(ce_handlers) expect(matched_handlers.uniq).to match_array(ce_handlers)
...@@ -34,7 +40,7 @@ describe Gitlab::Email::Handler do ...@@ -34,7 +40,7 @@ describe Gitlab::Email::Handler do
it 'can pick exactly one handler for each address' do it 'can pick exactly one handler for each address' do
addresses.each do |address| addresses.each do |address|
matched_handlers = ce_handlers.select do |handler| matched_handlers = ce_handlers.select do |handler|
handler.new('email', address).can_handle? handler.new(email, address).can_handle?
end end
expect(matched_handlers.count).to eq(1), "#{address} matches #{matched_handlers.count} handlers: #{matched_handlers}" expect(matched_handlers.count).to eq(1), "#{address} matches #{matched_handlers.count} handlers: #{matched_handlers}"
......
...@@ -52,10 +52,10 @@ describe Gitlab::ImportExport::MergeRequestParser do ...@@ -52,10 +52,10 @@ describe Gitlab::ImportExport::MergeRequestParser do
context 'when the diff is invalid' do context 'when the diff is invalid' do
let(:merge_request_diff) { build(:merge_request_diff, merge_request: merge_request, base_commit_sha: 'foobar') } let(:merge_request_diff) { build(:merge_request_diff, merge_request: merge_request, base_commit_sha: 'foobar') }
it 'sets the diff to nil' do it 'sets the diff to empty diff' do
expect(merge_request_diff).to be_invalid expect(merge_request_diff).to be_invalid
expect(merge_request_diff.merge_request).to eq merge_request expect(merge_request_diff.merge_request).to eq merge_request
expect(parsed_merge_request.merge_request_diff).to be_nil expect(parsed_merge_request.merge_request_diff).to be_empty
end end
end end
end end
......
...@@ -662,13 +662,12 @@ describe MergeRequest do ...@@ -662,13 +662,12 @@ describe MergeRequest do
end end
describe '#raw_diffs' do describe '#raw_diffs' do
let(:merge_request) { build(:merge_request) }
let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } } let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
context 'when there are MR diffs' do context 'when there are MR diffs' do
it 'delegates to the MR diffs' do let(:merge_request) { create(:merge_request, :with_diffs) }
merge_request.merge_request_diff = MergeRequestDiff.new
it 'delegates to the MR diffs' do
expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(options) expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(options)
merge_request.raw_diffs(options) merge_request.raw_diffs(options)
...@@ -676,6 +675,8 @@ describe MergeRequest do ...@@ -676,6 +675,8 @@ describe MergeRequest do
end end
context 'when there are no MR diffs' do context 'when there are no MR diffs' do
let(:merge_request) { build(:merge_request) }
it 'delegates to the compare object' do it 'delegates to the compare object' do
merge_request.compare = double(:compare) merge_request.compare = double(:compare)
......
...@@ -38,8 +38,8 @@ describe YoutrackService do ...@@ -38,8 +38,8 @@ describe YoutrackService do
expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123') expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123')
end end
it 'does not allow issue number to be followed by a letter' do it 'allows lowercase project key on the reference' do
expect(described_class.reference_pattern.match('YT-123A')).to eq(nil) expect(described_class.reference_pattern.match('yt-123')[:issue]).to eq('yt-123')
end end
end end
......
...@@ -21,4 +21,8 @@ RSpec.shared_examples 'allows project key on reference pattern' do |url_attr| ...@@ -21,4 +21,8 @@ RSpec.shared_examples 'allows project key on reference pattern' do |url_attr|
expect(described_class.reference_pattern.match('3EXT_EXT-1234')).to eq nil expect(described_class.reference_pattern.match('3EXT_EXT-1234')).to eq nil
expect(described_class.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234' expect(described_class.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234'
end end
it 'does not allow issue number to finish with a letter' do
expect(described_class.reference_pattern.match('EXT-123A')).to eq(nil)
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment