Skip to content
Snippets Groups Projects
Commit 18f78289 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 8191b157
No related branches found
No related tags found
No related merge requests found
Showing
with 432 additions and 34 deletions
import $ from 'jquery';
import BlobFileDropzone from '~/blob/blob_file_dropzone';
 
describe('BlobFileDropzone', function() {
describe('BlobFileDropzone', () => {
preloadFixtures('blob/show.html');
let dropzone;
let replaceFileButton;
const jQueryMock = {
enable: jest.fn(),
disable: jest.fn(),
};
 
beforeEach(() => {
loadFixtures('blob/show.html');
const form = $('.js-upload-blob-form');
this.blobFileDropzone = new BlobFileDropzone(form, 'POST');
this.dropzone = $('.js-upload-blob-form .dropzone').get(0).dropzone;
this.replaceFileButton = $('#submit-all');
// eslint-disable-next-line no-new
new BlobFileDropzone(form, 'POST');
dropzone = $('.js-upload-blob-form .dropzone').get(0).dropzone;
dropzone.processQueue = jest.fn();
replaceFileButton = $('#submit-all');
$.fn.extend(jQueryMock);
});
 
describe('submit button', () => {
it('requires file', () => {
spyOn(window, 'alert');
jest.spyOn(window, 'alert').mockImplementation(() => {});
 
this.replaceFileButton.click();
replaceFileButton.click();
 
expect(window.alert).toHaveBeenCalled();
});
 
it('is disabled while uploading', () => {
spyOn(window, 'alert');
jest.spyOn(window, 'alert').mockImplementation(() => {});
 
const file = new File([], 'some-file.jpg');
const fakeEvent = $.Event('drop', {
dataTransfer: { files: [file] },
});
 
this.dropzone.listeners[0].events.drop(fakeEvent);
this.replaceFileButton.click();
dropzone.listeners[0].events.drop(fakeEvent);
replaceFileButton.click();
 
expect(window.alert).not.toHaveBeenCalled();
expect(this.replaceFileButton.is(':disabled')).toEqual(true);
expect(jQueryMock.enable).toHaveBeenCalled();
expect(dropzone.processQueue).toHaveBeenCalled();
});
});
});
Loading
Loading
@@ -3,6 +3,12 @@
require 'spec_helper'
 
describe Gitlab::ImportExport::AfterExportStrategies::BaseAfterExportStrategy do
before do
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
end
let!(:service) { described_class.new }
let!(:project) { create(:project, :with_export) }
let(:shared) { project.import_export_shared }
Loading
Loading
Loading
Loading
@@ -5,6 +5,12 @@ require 'spec_helper'
describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
include StubRequests
 
before do
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
end
let(:example_url) { 'http://www.example.com' }
let(:strategy) { subject.new(url: example_url, http_method: 'post') }
let!(:project) { create(:project, :with_export) }
Loading
Loading
Loading
Loading
@@ -469,6 +469,7 @@ project:
- autoclose_referenced_issues
- status_page_setting
- requirements
- export_jobs
award_emoji:
- awardable
- user
Loading
Loading
Loading
Loading
@@ -291,6 +291,33 @@ describe Gitlab::QuickActions::Extractor do
expect(msg).to eq expected
end
 
it 'does not extract commands in multiline inline code on seperated rows' do
msg = "Hello\r\n`\r\nThis is some text\r\n/close\r\n/assign @user\r\n`\r\n\r\nWorld"
expected = msg.delete("\r")
msg, commands = extractor.extract_commands(msg)
expect(commands).to be_empty
expect(msg).to eq expected
end
it 'does not extract commands in multiline inline code starting from text' do
msg = "Hello `This is some text\r\n/close\r\n/assign @user\r\n`\r\n\r\nWorld"
expected = msg.delete("\r")
msg, commands = extractor.extract_commands(msg)
expect(commands).to be_empty
expect(msg).to eq expected
end
it 'does not extract commands in inline code' do
msg = "`This is some text\r\n/close\r\n/assign @user\r\n`\r\n\r\nWorld"
expected = msg.delete("\r")
msg, commands = extractor.extract_commands(msg)
expect(commands).to be_empty
expect(msg).to eq expected
end
it 'limits to passed commands when they are passed' do
msg = <<~MSG.strip
Hello, we should only extract the commands passed
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe ProjectExportJob, type: :model do
let(:project) { create(:project) }
let!(:job1) { create(:project_export_job, project: project, status: 0) }
let!(:job2) { create(:project_export_job, project: project, status: 2) }
describe 'associations' do
it { expect(job1).to belong_to(:project) }
end
describe 'validations' do
it { expect(job1).to validate_presence_of(:project) }
it { expect(job1).to validate_presence_of(:jid) }
it { expect(job1).to validate_presence_of(:status) }
end
end
Loading
Loading
@@ -3957,6 +3957,12 @@ describe Project do
describe '#remove_export' do
let(:project) { create(:project, :with_export) }
 
before do
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
end
it 'removes the export' do
project.remove_exports
 
Loading
Loading
@@ -5813,6 +5819,86 @@ describe Project do
end
end
 
describe '#add_export_job' do
context 'if not already present' do
it 'starts project export job' do
user = create(:user)
project = build(:project)
expect(ProjectExportWorker).to receive(:perform_async).with(user.id, project.id, nil, {})
project.add_export_job(current_user: user)
end
end
end
describe '#export_in_progress?' do
let(:project) { build(:project) }
let!(:project_export_job ) { create(:project_export_job, project: project) }
context 'when project export is enqueued' do
it { expect(project.export_in_progress?).to be false }
end
context 'when project export is in progress' do
before do
project_export_job.start!
end
it { expect(project.export_in_progress?).to be true }
end
context 'when project export is completed' do
before do
finish_job(project_export_job)
end
it { expect(project.export_in_progress?).to be false }
end
end
describe '#export_status' do
let(:project) { build(:project) }
let!(:project_export_job ) { create(:project_export_job, project: project) }
context 'when project export is enqueued' do
it { expect(project.export_status).to eq :queued }
end
context 'when project export is in progress' do
before do
project_export_job.start!
end
it { expect(project.export_status).to eq :started }
end
context 'when project export is completed' do
before do
finish_job(project_export_job)
allow(project).to receive(:export_file).and_return(double(ImportExportUploader, file: 'exists.zip'))
end
it { expect(project.export_status).to eq :finished }
end
context 'when project export is being regenerated' do
let!(:new_project_export_job ) { create(:project_export_job, project: project) }
before do
finish_job(project_export_job)
allow(project).to receive(:export_file).and_return(double(ImportExportUploader, file: 'exists.zip'))
end
it { expect(project.export_status).to eq :regeneration_in_progress }
end
end
def finish_job(export_job)
export_job.start
export_job.finish
end
def rugged_config
rugged_repo(project.repository).config
end
Loading
Loading
Loading
Loading
@@ -27,12 +27,9 @@ describe API::ProjectExport, :clean_gitlab_redis_cache do
 
before do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
# simulate exporting work directory
FileUtils.mkdir_p File.join(project_started.export_path, 'securerandom-hex')
# simulate in after export action
FileUtils.touch File.join(project_after_export.import_export_shared.lock_files_path, SecureRandom.hex)
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
end
 
after do
Loading
Loading
@@ -82,28 +79,42 @@ describe API::ProjectExport, :clean_gitlab_redis_cache do
expect(json_response['export_status']).to eq('none')
end
 
it 'is started' do
get api(path_started, user)
context 'when project export has started' do
before do
create(:project_export_job, project: project_started, status: 1)
end
 
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('started')
it 'returns status started' do
get api(path_started, user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('started')
end
end
 
it 'is after_export' do
get api(path_after_export, user)
context 'when project export has finished' do
it 'returns status finished' do
get api(path_finished, user)
 
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('after_export_action')
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('finished')
end
end
 
it 'is finished' do
get api(path_finished, user)
context 'when project export is being regenerated' do
before do
create(:project_export_job, project: project_finished, status: 1)
end
it 'returns status regeneration_in_progress' do
get api(path_finished, user)
 
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('finished')
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/project/export_status')
expect(json_response['export_status']).to eq('regeneration_in_progress')
end
end
end
 
Loading
Loading
Loading
Loading
@@ -362,6 +362,26 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do
end
end
 
context 'when bridge job status update raises state machine errors' do
let(:stub_config) { false }
before do
stub_ci_pipeline_yaml_file(YAML.dump(invalid: { yaml: 'error' }))
bridge.drop!
end
it 'tracks the exception' do
expect(Gitlab::ErrorTracking)
.to receive(:track_exception)
.with(
instance_of(Ci::Bridge::InvalidTransitionError),
bridge_id: bridge.id,
downstream_pipeline_id: kind_of(Numeric))
service.execute(bridge)
end
end
context 'when bridge job has YAML variables defined' do
before do
bridge.yaml_variables = [{ key: 'BRIDGE', value: 'var', public: true }]
Loading
Loading
Loading
Loading
@@ -22,6 +22,24 @@ describe Ci::PipelineBridgeStatusService do
 
subject
end
context 'when bridge job status raises state machine errors' do
before do
pipeline.drop!
bridge.drop!
end
it 'tracks the exception' do
expect(Gitlab::ErrorTracking)
.to receive(:track_exception)
.with(
instance_of(Ci::Bridge::InvalidTransitionError),
bridge_id: bridge.id,
downstream_pipeline_id: pipeline.id)
subject
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe ProjectExportOptions do
let(:project) { create(:project) }
let(:project_export_job) { create(:project_export_job, project: project, jid: '123', status: 1) }
let(:job) { { 'args' => [project.owner.id, project.id, nil, nil], 'jid' => '123' } }
let(:worker_class) do
Class.new do
include Sidekiq::Worker
include ProjectExportOptions
end
end
it 'sets default retry limit' do
expect(worker_class.sidekiq_options['retry']).to eq(ProjectExportOptions::EXPORT_RETRY_COUNT)
end
it 'sets default status expiration' do
expect(worker_class.sidekiq_options['status_expiration']).to eq(StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION)
end
describe '.sidekiq_retries_exhausted' do
it 'marks status as failed' do
expect { worker_class.sidekiq_retries_exhausted_block.call(job) }.to change { project_export_job.reload.status }.from(1).to(3)
end
context 'when status update fails' do
before do
project_export_job.update(status: 2)
end
it 'logs an error' do
expect(Sidekiq.logger).to receive(:error).with("Failed to set Job #{job['jid']} for project #{project.id} to failed state")
worker_class.sidekiq_retries_exhausted_block.call(job)
end
end
end
end
Loading
Loading
@@ -9,21 +9,59 @@ describe ProjectExportWorker do
subject { described_class.new }
 
describe '#perform' do
before do
allow_next_instance_of(described_class) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
end
context 'when it succeeds' do
it 'calls the ExportService' do
expect_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute)
 
subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' })
end
context 'export job' do
before do
allow_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute)
end
it 'creates an export job record for the project' do
expect { subject.perform(user.id, project.id, {}) }.to change { project.export_jobs.count }.from(0).to(1)
end
it 'sets the export job status to started' do
expect_next_instance_of(ProjectExportJob) do |job|
expect(job).to receive(:start)
end
subject.perform(user.id, project.id, {})
end
it 'sets the export job status to finished' do
expect_next_instance_of(ProjectExportJob) do |job|
expect(job).to receive(:finish)
end
subject.perform(user.id, project.id, {})
end
end
end
 
context 'when it fails' do
it 'raises an exception when params are invalid' do
it 'does not raise an exception when strategy is invalid' do
expect_any_instance_of(::Projects::ImportExport::ExportService).not_to receive(:execute)
 
expect { subject.perform(1234, project.id, {}) }.to raise_exception(ActiveRecord::RecordNotFound)
expect { subject.perform(user.id, 1234, {}) }.to raise_exception(ActiveRecord::RecordNotFound)
expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.to raise_exception(Gitlab::ImportExport::AfterExportStrategyBuilder::StrategyNotFoundError)
expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.not_to raise_error
end
it 'does not raise error when project cannot be found' do
expect { subject.perform(user.id, -234, {}) }.not_to raise_error
end
it 'does not raise error when user cannot be found' do
expect { subject.perform(-863, project.id, {}) }.not_to raise_error
end
end
end
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe StuckExportJobsWorker do
let(:worker) { described_class.new }
shared_examples 'project export job detection' do
context 'when the job has completed' do
context 'when the export status was already updated' do
before do
allow(Gitlab::SidekiqStatus).to receive(:completed_jids) do
project_export_job.start
project_export_job.finish
[project_export_job.jid]
end
end
it 'does not mark the export as failed' do
worker.perform
expect(project_export_job.reload.finished?).to be true
end
end
context 'when the export status was not updated' do
before do
allow(Gitlab::SidekiqStatus).to receive(:completed_jids) do
project_export_job.start
[project_export_job.jid]
end
end
it 'marks the project as failed' do
worker.perform
expect(project_export_job.reload.failed?).to be true
end
end
context 'when the job is not in queue and db record in queued state' do
before do
allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([project_export_job.jid])
end
it 'marks the project as failed' do
expect(project_export_job.queued?).to be true
worker.perform
expect(project_export_job.reload.failed?).to be true
end
end
end
context 'when the job is running in Sidekiq' do
before do
allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([])
end
it 'does not mark the project export as failed' do
expect { worker.perform }.not_to change { project_export_job.reload.status }
end
end
end
describe 'with started export status' do
it_behaves_like 'project export job detection' do
let(:project) { create(:project) }
let!(:project_export_job) { create(:project_export_job, project: project, jid: '123') }
end
end
end
Loading
Loading
@@ -1866,14 +1866,14 @@ autosize@^4.0.2:
resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.2.tgz#073cfd07c8bf45da4b9fd153437f5bafbba1e4c9"
integrity sha512-jnSyH2d+qdfPGpWlcuhGiHmqBJ6g3X+8T+iRwFrHPLVcdoGJE/x6Qicm6aDHfTsbgZKxyV8UU/YB2p4cjKDRRA==
 
aws-sdk@^2.526.0:
version "2.526.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.526.0.tgz#e0f899be59edb7d50eb8cca7978bcd401a5d48c2"
integrity sha512-ZZqf8AnD9A8ZJd/4oU711R8taxm8sV7wcAOvT0HhrZxv8zASAzoz2lpZ19QAil6uJ52IOkq4ij/zGy7VBXEgPA==
aws-sdk@^2.637.0:
version "2.637.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.637.0.tgz#810e25e53acf2250d35fc74498f9d4492e154217"
integrity sha512-e7EYX5rNtQyEaleQylUtLSNKXOmvOwfifQ4bYkfF80mFsVI3DSydczLHXrqPzXoEJaS/GI/9HqVnlQcPs6Q3ew==
dependencies:
buffer "4.9.1"
events "1.1.1"
ieee754 "1.1.8"
ieee754 "1.1.13"
jmespath "0.15.0"
querystring "0.2.0"
sax "1.2.1"
Loading
Loading
@@ -5752,10 +5752,10 @@ icss-utils@^2.1.0:
dependencies:
postcss "^6.0.1"
 
ieee754@1.1.8, ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
integrity sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=
ieee754@1.1.13, ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
 
iferr@^0.1.5:
version "0.1.5"
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment