# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ::Packages::Maven::Metadata::CreateVersionsXmlService do
let_it_be(:package) { create(:maven_package, version: nil) }
let(:versions_in_database) { %w[1.3 2.0-SNAPSHOT 1.6 1.4 1.5-SNAPSHOT] }
let(:versions_in_xml) { %w[1.3 2.0-SNAPSHOT 1.6 1.4 1.5-SNAPSHOT] }
let(:version_latest) { nil }
let(:version_release) { '1.4' }
let(:service) { described_class.new(metadata_content: metadata_xml, package: package) }
describe '#execute' do
subject { service.execute }
before do
next unless package
versions_in_database.each do |version|
create(:maven_package, name: package.name, version: version, project: package.project)
end
end
shared_examples 'returning an xml with versions in the database' do
it 'returns an metadata versions xml with versions in the database', :aggregate_failures do
result = subject
expect(result).to be_success
expect(versions_from(result.payload[:metadata_content])).to match_array(versions_in_database)
end
end
shared_examples 'returning an xml with' do |release:, latest:|
it 'returns an xml with the updated release and latest versions', :aggregate_failures do
result = subject
expect(result).to be_success
expect(result.payload[:changes_exist]).to be_truthy
xml = result.payload[:metadata_content]
expect(release_from(xml)).to eq(release)
expect(latest_from(xml)).to eq(latest)
end
end
context 'with same versions in both sides' do
it 'returns no changes', :aggregate_failures do
result = subject
expect(result).to be_success
expect(result.payload).to eq(changes_exist: false, empty_versions: false)
end
end
context 'with more versions' do
let(:additional_versions) { %w[5.5 5.6 5.7-SNAPSHOT] }
context 'in the xml side' do
let(:versions_in_xml) { versions_in_database + additional_versions }
it_behaves_like 'returning an xml with versions in the database'
end
context 'in the database side' do
let(:versions_in_database) { versions_in_xml + additional_versions }
it_behaves_like 'returning an xml with versions in the database'
end
end
context 'with completely different versions' do
let(:versions_in_database) { %w[1.0 1.1 1.2] }
let(:versions_in_xml) { %w[2.0 2.1 2.2] }
it_behaves_like 'returning an xml with versions in the database'
end
context 'with no versions in the database' do
let(:versions_in_database) { [] }
it 'returns a success', :aggregate_failures do
result = subject
expect(result).to be_success
expect(result.payload).to eq(changes_exist: true, empty_versions: true)
end
context 'with an xml without a release version' do
let(:version_release) { nil }
it 'returns a success', :aggregate_failures do
result = subject
expect(result).to be_success
expect(result.payload).to eq(changes_exist: true, empty_versions: true)
end
end
end
context 'with differences in both sides' do
let(:shared_versions) { %w[1.3 2.0-SNAPSHOT 1.6 1.4 1.5-SNAPSHOT] }
let(:additional_versions_in_xml) { %w[5.5 5.6 5.7-SNAPSHOT] }
let(:versions_in_xml) { shared_versions + additional_versions_in_xml }
let(:additional_versions_in_database) { %w[6.5 6.6 6.7-SNAPSHOT] }
let(:versions_in_database) { shared_versions + additional_versions_in_database }
it_behaves_like 'returning an xml with versions in the database'
end
context 'with a new release and latest from the database' do
let(:versions_in_database) { versions_in_xml + %w[4.1 4.2-SNAPSHOT] }
it_behaves_like 'returning an xml with', release: '4.1', latest: nil
context 'with a latest in the xml' do
let(:version_latest) { '1.6' }
it_behaves_like 'returning an xml with', release: '4.1', latest: '4.2-SNAPSHOT'
end
end
context 'with release and latest not existing in the database' do
let(:version_release) { '7.0' }
let(:version_latest) { '8.0-SNAPSHOT' }
it_behaves_like 'returning an xml with', release: '1.4', latest: '1.5-SNAPSHOT'
end
context 'with added versions in the database side no more recent than release' do
let(:versions_in_database) { versions_in_xml + %w[4.1 4.2-SNAPSHOT] }
before do
::Packages::Package.find_by(name: package.name, version: '4.1').update!(created_at: 2.weeks.ago)
::Packages::Package.find_by(name: package.name, version: '4.2-SNAPSHOT').update!(created_at: 2.weeks.ago)
end
it_behaves_like 'returning an xml with', release: '1.4', latest: nil
context 'with a latest in the xml' do
let(:version_latest) { '1.6' }
it_behaves_like 'returning an xml with', release: '1.4', latest: '1.5-SNAPSHOT'
end
end
context 'only snapshot versions are in the database' do
let(:versions_in_database) { %w[4.2-SNAPSHOT] }
it_behaves_like 'returning an xml with', release: nil, latest: nil
it 'returns an xml without any release element' do
result = subject
xml_doc = Nokogiri::XML(result.payload[:metadata_content])
expect(xml_doc.xpath('//metadata/versioning/release')).to be_empty
end
end
context 'last updated timestamp' do
let(:versions_in_database) { versions_in_xml + %w[4.1 4.2-SNAPSHOT] }
it 'updates the last updated timestamp' do
original = last_updated_from(metadata_xml)
result = subject
expect(result).to be_success
expect(original).not_to eq(last_updated_from(result.payload[:metadata_content]))
end
end
context 'with an incomplete metadata content' do
let(:metadata_xml) { '' }
it_behaves_like 'returning an error service response', message: 'metadata_content is invalid'
end
context 'with an invalid metadata content' do
let(:metadata_xml) { '' }
it_behaves_like 'returning an error service response', message: 'metadata_content is invalid'
end
it_behaves_like 'handling metadata content pointing to a file for the create xml service'
it_behaves_like 'handling invalid parameters for create xml service'
end
def metadata_xml
Nokogiri::XML::Builder.new do |xml|
xml.metadata do
xml.groupId(package.maven_metadatum.app_group)
xml.artifactId(package.maven_metadatum.app_name)
xml.versioning do
xml.release(version_release) if version_release
xml.latest(version_latest) if version_latest
xml.lastUpdated('20210113130531')
xml.versions do
versions_in_xml.each do |version|
xml.version(version)
end
end
end
end
end.to_xml
end
def versions_from(xml_content)
doc = Nokogiri::XML(xml_content)
doc.xpath('//metadata/versioning/versions/version').map(&:content)
end
def release_from(xml_content)
doc = Nokogiri::XML(xml_content)
doc.xpath('//metadata/versioning/release').first&.content
end
def latest_from(xml_content)
doc = Nokogiri::XML(xml_content)
doc.xpath('//metadata/versioning/latest').first&.content
end
def last_updated_from(xml_content)
doc = Nokogiri::XML(xml_content)
doc.xpath('//metadata/versioning/lastUpdated').first.content
end
end