1# frozen_string_literal: true 2require 'spec_helper' 3 4RSpec.describe Submodules::UpdateService do 5 let(:project) { create(:project, :repository) } 6 let(:repository) { project.repository } 7 let(:user) { create(:user, :commit_email) } 8 let(:branch_name) { project.default_branch } 9 let(:submodule) { 'six' } 10 let(:commit_sha) { 'e25eda1fece24ac7a03624ed1320f82396f35bd8' } 11 let(:commit_message) { 'whatever' } 12 let(:current_sha) { repository.blob_at('HEAD', submodule).id } 13 let(:commit_params) do 14 { 15 submodule: submodule, 16 commit_message: commit_message, 17 commit_sha: commit_sha, 18 branch_name: branch_name 19 } 20 end 21 22 subject { described_class.new(project, user, commit_params) } 23 24 describe "#execute" do 25 shared_examples 'returns error result' do 26 it do 27 result = subject.execute 28 29 expect(result[:status]).to eq :error 30 expect(result[:message]).to eq error_message 31 end 32 end 33 34 context 'when the user is not authorized' do 35 it_behaves_like 'returns error result' do 36 let(:error_message) { 'You are not allowed to push into this branch' } 37 end 38 end 39 40 context 'when the user is authorized' do 41 before do 42 project.add_maintainer(user) 43 end 44 45 context 'when the branch is protected' do 46 before do 47 create(:protected_branch, :no_one_can_push, project: project, name: branch_name) 48 end 49 50 it_behaves_like 'returns error result' do 51 let(:error_message) { 'You are not allowed to push into this branch' } 52 end 53 end 54 55 context 'validations' do 56 context 'when submodule' do 57 context 'is empty' do 58 let(:submodule) { '' } 59 60 it_behaves_like 'returns error result' do 61 let(:error_message) { 'Invalid parameters' } 62 end 63 end 64 65 context 'is not present' do 66 let(:submodule) { nil } 67 68 it_behaves_like 'returns error result' do 69 let(:error_message) { 'Invalid parameters' } 70 end 71 end 72 73 context 'is invalid' do 74 let(:submodule) { 'VERSION' } 75 76 it_behaves_like 'returns error result' do 77 let(:error_message) { 'Invalid submodule path' } 78 end 79 end 80 81 context 'does not exist' do 82 let(:submodule) { 'non-existent-submodule' } 83 84 it_behaves_like 'returns error result' do 85 let(:error_message) { 'Invalid submodule path' } 86 end 87 end 88 89 context 'has traversal path' do 90 let(:submodule) { '../six' } 91 92 it_behaves_like 'returns error result' do 93 let(:error_message) { 'Invalid submodule path' } 94 end 95 end 96 end 97 98 context 'commit_sha' do 99 context 'is empty' do 100 let(:commit_sha) { '' } 101 102 it_behaves_like 'returns error result' do 103 let(:error_message) { 'Invalid parameters' } 104 end 105 end 106 107 context 'is not present' do 108 let(:commit_sha) { nil } 109 110 it_behaves_like 'returns error result' do 111 let(:error_message) { 'Invalid parameters' } 112 end 113 end 114 115 context 'is invalid' do 116 let(:commit_sha) { '1' } 117 118 it_behaves_like 'returns error result' do 119 let(:error_message) { 'Invalid parameters' } 120 end 121 end 122 123 context 'is the same as the current ref' do 124 let(:commit_sha) { current_sha } 125 126 it_behaves_like 'returns error result' do 127 let(:error_message) { "The submodule #{submodule} is already at #{commit_sha}" } 128 end 129 end 130 end 131 132 context 'branch_name' do 133 context 'is empty' do 134 let(:branch_name) { '' } 135 136 it_behaves_like 'returns error result' do 137 let(:error_message) { 'You can only create or edit files when you are on a branch' } 138 end 139 end 140 141 context 'is not present' do 142 let(:branch_name) { nil } 143 144 it_behaves_like 'returns error result' do 145 let(:error_message) { 'Invalid parameters' } 146 end 147 end 148 149 context 'does not exist' do 150 let(:branch_name) { 'non/existent-branch' } 151 152 it_behaves_like 'returns error result' do 153 let(:error_message) { 'You can only create or edit files when you are on a branch' } 154 end 155 end 156 157 context 'when commit message is empty' do 158 let(:commit_message) { '' } 159 160 it 'a default commit message is set' do 161 message = "Update submodule #{submodule} with oid #{commit_sha}" 162 163 expect(repository).to receive(:update_submodule).with(any_args, hash_including(message: message)) 164 165 subject.execute 166 end 167 end 168 end 169 end 170 171 context 'when there is an unexpected error' do 172 before do 173 allow(repository).to receive(:update_submodule).and_raise(StandardError, 'error message') 174 end 175 176 it_behaves_like 'returns error result' do 177 let(:error_message) { 'error message' } 178 end 179 end 180 181 it 'updates the submodule reference' do 182 result = subject.execute 183 184 expect(result[:status]).to eq :success 185 expect(result[:result]).to eq repository.head_commit.id 186 expect(repository.blob_at('HEAD', submodule).id).to eq commit_sha 187 end 188 189 context 'when submodule is inside a directory' do 190 let(:submodule) { 'test_inside_folder/another_folder/six' } 191 let(:branch_name) { 'submodule_inside_folder' } 192 193 it 'updates the submodule reference' do 194 expect(repository.blob_at(branch_name, submodule).id).not_to eq commit_sha 195 196 subject.execute 197 198 expect(repository.blob_at(branch_name, submodule).id).to eq commit_sha 199 end 200 end 201 202 context 'when repository is empty' do 203 let(:project) { create(:project, :empty_repo) } 204 let(:branch_name) { 'master' } 205 206 it_behaves_like 'returns error result' do 207 let(:error_message) { 'The repository is empty' } 208 end 209 end 210 end 211 end 212end 213