diff options
Diffstat (limited to 'spec/lib/gitlab/ci/config/external/file/component_spec.rb')
-rw-r--r-- | spec/lib/gitlab/ci/config/external/file/component_spec.rb | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/spec/lib/gitlab/ci/config/external/file/component_spec.rb b/spec/lib/gitlab/ci/config/external/file/component_spec.rb new file mode 100644 index 00000000000..a162a1a8abf --- /dev/null +++ b/spec/lib/gitlab/ci/config/external/file/component_spec.rb @@ -0,0 +1,179 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Config::External::File::Component, feature_category: :pipeline_authoring do + let_it_be(:context_project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } + let_it_be(:project_variables) { project.predefined_variables } + + let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } + let(:external_resource) { described_class.new(params, context) } + let(:params) { { component: 'gitlab.com/acme/components/my-component@1.0' } } + let(:fetch_service) { instance_double(::Ci::Components::FetchService) } + let(:response) { ServiceResponse.error(message: 'some error message') } + + let(:context_params) do + { + project: context_project, + sha: '12345', + user: user, + variables: project_variables + } + end + + before do + allow(::Ci::Components::FetchService) + .to receive(:new) + .with( + address: params[:component], + current_user: context.user + ).and_return(fetch_service) + + allow(fetch_service).to receive(:execute).and_return(response) + end + + describe '#matching?' do + subject(:matching) { external_resource.matching? } + + context 'when component is specified' do + let(:params) { { component: 'some-value' } } + + it { is_expected.to be_truthy } + + context 'when feature flag ci_include_components is disabled' do + before do + stub_feature_flags(ci_include_components: false) + end + + it { is_expected.to be_falsey } + end + end + + context 'when component is not specified' do + let(:params) { { local: 'some-value' } } + + it { is_expected.to be_falsy } + end + end + + describe '#valid?' do + subject(:valid?) do + Gitlab::Ci::Config::External::Mapper::Verifier.new(context).process([external_resource]) + external_resource.valid? + end + + context 'when the context project does not have a repository' do + before do + allow(context_project).to receive(:repository).and_return(nil) + end + + it 'is invalid' do + expect(subject).to be_falsy + expect(external_resource.error_message).to eq('Unable to use components outside of a project context') + end + end + + context 'when location is not provided' do + let(:params) { { component: 123 } } + + it 'is invalid' do + expect(subject).to be_falsy + expect(external_resource.error_message).to eq('Included file `123` needs to be a string') + end + end + + context 'when component path is provided' do + context 'when component is not found' do + let(:response) do + ServiceResponse.error(message: 'Content not found') + end + + it 'is invalid' do + expect(subject).to be_falsy + expect(external_resource.error_message).to eq('Content not found') + end + end + + context 'when component is found' do + let(:content) do + <<~COMPONENT + job: + script: echo + COMPONENT + end + + let(:response) do + ServiceResponse.success(payload: { + content: content, + path: instance_double(::Gitlab::Ci::Components::InstancePath, project: project, sha: '12345') + }) + end + + it 'is valid' do + expect(subject).to be_truthy + expect(external_resource.content).to eq(content) + end + + context 'when content is not a valid YAML' do + let(:content) { 'the-content' } + + it 'is invalid' do + expect(subject).to be_falsy + expect(external_resource.error_message).to match(/does not have valid YAML syntax/) + end + end + end + end + end + + describe '#metadata' do + subject(:metadata) { external_resource.metadata } + + let(:component_path) do + instance_double(::Gitlab::Ci::Components::InstancePath, + project: project, + sha: '12345', + project_file_path: 'my-component/template.yml') + end + + let(:response) do + ServiceResponse.success(payload: { path: component_path }) + end + + it 'returns the metadata' do + is_expected.to include( + context_project: context_project.full_path, + context_sha: context.sha, + type: :component, + location: 'gitlab.com/acme/components/my-component@1.0', + blob: a_string_ending_with("#{project.full_path}/-/blob/12345/my-component/template.yml"), + raw: nil, + extra: {} + ) + end + end + + describe '#expand_context' do + let(:component_path) do + instance_double(::Gitlab::Ci::Components::InstancePath, + project: project, + sha: '12345') + end + + let(:response) do + ServiceResponse.success(payload: { path: component_path }) + end + + subject { external_resource.send(:expand_context_attrs) } + + it 'inherits user and variables while changes project and sha' do + is_expected.to include( + project: project, + sha: '12345', + user: context.user, + variables: context.variables) + end + end +end |