2021-03-11 19:13:27 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
RSpec.describe Gitlab::Changelog::Config do
|
2021-11-11 11:23:49 +05:30
|
|
|
include ProjectForksHelper
|
|
|
|
|
2021-03-11 19:13:27 +05:30
|
|
|
let(:project) { build_stubbed(:project) }
|
|
|
|
|
|
|
|
describe '.from_git' do
|
|
|
|
it 'retrieves the configuration from Git' do
|
|
|
|
allow(project.repository)
|
|
|
|
.to receive(:changelog_config)
|
|
|
|
.and_return("---\ndate_format: '%Y'")
|
|
|
|
|
|
|
|
expect(described_class)
|
|
|
|
.to receive(:from_hash)
|
2021-11-11 11:23:49 +05:30
|
|
|
.with(project, { 'date_format' => '%Y' }, nil)
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
described_class.from_git(project)
|
|
|
|
end
|
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
it "retrieves the specified configuration from git" do
|
|
|
|
allow(project.repository)
|
|
|
|
.to receive(:changelog_config).with('HEAD', 'specified_changelog_config.yml')
|
|
|
|
.and_return("---\ndate_format: '%Y'")
|
|
|
|
|
|
|
|
expect(described_class)
|
|
|
|
.to receive(:from_hash)
|
|
|
|
.with(project, { 'date_format' => '%Y' }, nil)
|
|
|
|
|
|
|
|
described_class.from_git(project, nil, 'specified_changelog_config.yml')
|
|
|
|
end
|
|
|
|
|
2021-03-11 19:13:27 +05:30
|
|
|
it 'returns the default configuration when no YAML file exists in Git' do
|
|
|
|
allow(project.repository)
|
|
|
|
.to receive(:changelog_config)
|
|
|
|
.and_return(nil)
|
|
|
|
|
|
|
|
expect(described_class)
|
|
|
|
.to receive(:new)
|
|
|
|
.with(project)
|
|
|
|
|
|
|
|
described_class.from_git(project)
|
|
|
|
end
|
2022-04-04 11:22:00 +05:30
|
|
|
|
|
|
|
context 'when changelog is empty' do
|
|
|
|
it 'returns the default configuration' do
|
|
|
|
allow(project.repository)
|
|
|
|
.to receive(:changelog_config)
|
|
|
|
.and_return("")
|
|
|
|
|
|
|
|
expect(described_class)
|
|
|
|
.to receive(:new)
|
|
|
|
.with(project)
|
|
|
|
|
|
|
|
described_class.from_git(project)
|
|
|
|
end
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '.from_hash' do
|
|
|
|
it 'sets the configuration according to a Hash' do
|
2021-11-11 11:23:49 +05:30
|
|
|
user1 = create(:user)
|
|
|
|
user2 = create(:user)
|
|
|
|
user3 = create(:user)
|
|
|
|
group = create(:group, path: 'group')
|
|
|
|
group2 = create(:group, path: 'group-path')
|
|
|
|
group.add_developer(user1)
|
|
|
|
group.add_developer(user2)
|
|
|
|
group2.add_developer(user3)
|
|
|
|
|
2021-03-11 19:13:27 +05:30
|
|
|
config = described_class.from_hash(
|
|
|
|
project,
|
2021-11-11 11:23:49 +05:30
|
|
|
{
|
|
|
|
'date_format' => 'foo',
|
|
|
|
'template' => 'bar',
|
|
|
|
'categories' => { 'foo' => 'bar' },
|
|
|
|
'tag_regex' => 'foo',
|
|
|
|
'include_groups' => %w[group group-path non-existent-group]
|
|
|
|
},
|
|
|
|
user1
|
2021-03-11 19:13:27 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
expect(config.date_format).to eq('foo')
|
|
|
|
expect(config.template)
|
2021-09-30 23:02:18 +05:30
|
|
|
.to be_instance_of(Gitlab::TemplateParser::AST::Expressions)
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
expect(config.categories).to eq({ 'foo' => 'bar' })
|
2021-04-29 21:17:54 +05:30
|
|
|
expect(config.tag_regex).to eq('foo')
|
2021-11-11 11:23:49 +05:30
|
|
|
expect(config.always_credit_user_ids).to match_array([user1.id, user2.id, user3.id])
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'raises Error when the categories are not a Hash' do
|
|
|
|
expect { described_class.from_hash(project, 'categories' => 10) }
|
|
|
|
.to raise_error(Gitlab::Changelog::Error)
|
|
|
|
end
|
2021-09-30 23:02:18 +05:30
|
|
|
|
|
|
|
it 'raises a Gitlab::Changelog::Error when the template is invalid' do
|
|
|
|
invalid_template = <<~TPL
|
|
|
|
{% each {{foo}} %}
|
|
|
|
{% end %}
|
|
|
|
TPL
|
|
|
|
|
|
|
|
expect { described_class.from_hash(project, 'template' => invalid_template) }
|
|
|
|
.to raise_error(Gitlab::Changelog::Error)
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '#contributor?' do
|
2021-11-11 11:23:49 +05:30
|
|
|
let(:project) { create(:project, :public, :repository) }
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
context 'when user is a member of project' do
|
|
|
|
let(:user) { create(:user) }
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
before do
|
|
|
|
project.add_developer(user)
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
it { expect(described_class.new(project).contributor?(user)).to eq(false) }
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
context 'when user has at least one merge request merged into default_branch' do
|
|
|
|
let(:contributor) { create(:user) }
|
|
|
|
let(:user_without_access) { create(:user) }
|
|
|
|
let(:user_fork) { fork_project(project, contributor, repository: true) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:merge_request, :merged,
|
|
|
|
author: contributor,
|
|
|
|
target_project: project,
|
|
|
|
source_project: user_fork,
|
|
|
|
target_branch: project.default_branch.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { expect(described_class.new(project).contributor?(contributor)).to eq(true) }
|
|
|
|
it { expect(described_class.new(project).contributor?(user_without_access)).to eq(false) }
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#category' do
|
|
|
|
it 'returns the name of a category' do
|
|
|
|
config = described_class.new(project)
|
|
|
|
|
|
|
|
config.categories['foo'] = 'Foo'
|
|
|
|
|
|
|
|
expect(config.category('foo')).to eq('Foo')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns the raw category name when no alternative name is configured' do
|
|
|
|
config = described_class.new(project)
|
|
|
|
|
|
|
|
expect(config.category('bla')).to eq('bla')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#format_date' do
|
|
|
|
it 'formats a date according to the configured date format' do
|
|
|
|
config = described_class.new(project)
|
|
|
|
time = Time.utc(2021, 1, 5)
|
|
|
|
|
|
|
|
expect(config.format_date(time)).to eq('2021-01-05')
|
|
|
|
end
|
|
|
|
end
|
2021-11-11 11:23:49 +05:30
|
|
|
|
|
|
|
describe '#always_credit_author?' do
|
|
|
|
let_it_be(:group_member) { create(:user) }
|
|
|
|
let_it_be(:non_group_member) { create(:user) }
|
|
|
|
let_it_be(:group) { create(:group, :private, path: 'group') }
|
|
|
|
|
|
|
|
before do
|
|
|
|
group.add_developer(group_member)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when include_groups is defined' do
|
|
|
|
context 'when user generating changelog has access to group' do
|
|
|
|
it 'returns whether author should always be credited' do
|
|
|
|
config = described_class.from_hash(
|
|
|
|
project,
|
|
|
|
{ 'include_groups' => ['group'] },
|
|
|
|
group_member
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(config.always_credit_author?(group_member)).to eq(true)
|
|
|
|
expect(config.always_credit_author?(non_group_member)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user generating changelog has no access to group' do
|
|
|
|
it 'always returns false' do
|
|
|
|
config = described_class.from_hash(
|
|
|
|
project,
|
|
|
|
{ 'include_groups' => ['group'] },
|
|
|
|
non_group_member
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(config.always_credit_author?(group_member)).to eq(false)
|
|
|
|
expect(config.always_credit_author?(non_group_member)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when include_groups is not defined' do
|
|
|
|
it 'always returns false' do
|
|
|
|
config = described_class.from_hash(
|
|
|
|
project,
|
|
|
|
{},
|
|
|
|
group_member
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(config.always_credit_author?(group_member)).to eq(false)
|
|
|
|
expect(config.always_credit_author?(non_group_member)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|