Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-02 00:10:21 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-02 00:10:21 +0300
commit5b8f2c8a24237cc5b2e2ba365b79e6293b93e459 (patch)
tree6ce5ce8932acbe93832fc0476f323e95bbb7dd8f /spec
parent304e230182b74eb84833c60b50618a5f0d7e2f9a (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/packages.rb6
-rw-r--r--spec/frontend/profile/account/components/delete_account_modal_spec.js82
-rw-r--r--spec/graphql/types/package_type_enum_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb31
-rw-r--r--spec/lib/gitlab/regex_spec.rb17
-rw-r--r--spec/models/ci/pipeline_artifact_spec.rb10
-rw-r--r--spec/models/packages/package_spec.rb29
-rw-r--r--spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb (renamed from spec/lib/gitlab/ci/pipeline/artifact/code_coverage_spec.rb)7
-rw-r--r--spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb134
-rw-r--r--spec/services/ci/generate_coverage_reports_service_spec.rb3
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb1
-rw-r--r--spec/support/test_reports/test_reports_helper.rb4
12 files changed, 266 insertions, 60 deletions
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index 0f9138ddefe..ee9079579e0 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -121,6 +121,12 @@ FactoryBot.define do
conan_metadatum { build(:conan_metadatum, package: nil) }
end
end
+
+ factory :generic_package do
+ sequence(:name) { |n| "generic-package-#{n}" }
+ version { '1.0.0' }
+ package_type { :generic }
+ end
end
factory :composer_metadatum, class: 'Packages::Composer::Metadatum' do
diff --git a/spec/frontend/profile/account/components/delete_account_modal_spec.js b/spec/frontend/profile/account/components/delete_account_modal_spec.js
index 4da82152818..7834456f7c4 100644
--- a/spec/frontend/profile/account/components/delete_account_modal_spec.js
+++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js
@@ -1,21 +1,49 @@
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { merge } from 'lodash';
+import { mount } from '@vue/test-utils';
import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue';
+const GlModalStub = {
+ name: 'gl-modal-stub',
+ template: `
+ <div>
+ <slot></slot>
+ </div>
+ `,
+};
+
describe('DeleteAccountModal component', () => {
const actionUrl = `${TEST_HOST}/delete/user`;
const username = 'hasnoname';
- let Component;
+ let wrapper;
let vm;
- beforeEach(() => {
- Component = Vue.extend(deleteAccountModal);
- });
+ const createWrapper = (options = {}) => {
+ wrapper = mount(
+ deleteAccountModal,
+ merge(
+ {},
+ {
+ propsData: {
+ actionUrl,
+ username,
+ },
+ stubs: {
+ GlModal: GlModalStub,
+ },
+ },
+ options,
+ ),
+ );
+ vm = wrapper.vm;
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
+ vm = null;
});
const findElements = () => {
@@ -23,16 +51,16 @@ describe('DeleteAccountModal component', () => {
return {
form: vm.$refs.form,
input: vm.$el.querySelector(`[name="${confirmation}"]`),
- submitButton: vm.$el.querySelector('.btn-danger'),
};
};
+ const findModal = () => wrapper.find(GlModalStub);
describe('with password confirmation', () => {
beforeEach(done => {
- vm = mountComponent(Component, {
- actionUrl,
- confirmWithPassword: true,
- username,
+ createWrapper({
+ propsData: {
+ confirmWithPassword: true,
+ },
});
vm.isOpen = true;
@@ -43,7 +71,7 @@ describe('DeleteAccountModal component', () => {
});
it('does not accept empty password', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = '';
input.dispatchEvent(new Event('input'));
@@ -51,8 +79,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredPassword).toBe(input.value);
- expect(submitButton).toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
expect(form.submit).not.toHaveBeenCalled();
})
@@ -61,7 +89,7 @@ describe('DeleteAccountModal component', () => {
});
it('submits form with password', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'anything';
input.dispatchEvent(new Event('input'));
@@ -69,8 +97,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredPassword).toBe(input.value);
- expect(submitButton).not.toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
expect(form.submit).toHaveBeenCalled();
})
@@ -81,10 +109,10 @@ describe('DeleteAccountModal component', () => {
describe('with username confirmation', () => {
beforeEach(done => {
- vm = mountComponent(Component, {
- actionUrl,
- confirmWithPassword: false,
- username,
+ createWrapper({
+ propsData: {
+ confirmWithPassword: false,
+ },
});
vm.isOpen = true;
@@ -95,7 +123,7 @@ describe('DeleteAccountModal component', () => {
});
it('does not accept wrong username', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'this is wrong';
input.dispatchEvent(new Event('input'));
@@ -103,8 +131,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredUsername).toBe(input.value);
- expect(submitButton).toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
expect(form.submit).not.toHaveBeenCalled();
})
@@ -113,7 +141,7 @@ describe('DeleteAccountModal component', () => {
});
it('submits form with correct username', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = username;
input.dispatchEvent(new Event('input'));
@@ -121,8 +149,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredUsername).toBe(input.value);
- expect(submitButton).not.toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
expect(form.submit).toHaveBeenCalled();
})
diff --git a/spec/graphql/types/package_type_enum_spec.rb b/spec/graphql/types/package_type_enum_spec.rb
index fadec9744ed..80a20a68bc2 100644
--- a/spec/graphql/types/package_type_enum_spec.rb
+++ b/spec/graphql/types/package_type_enum_spec.rb
@@ -4,6 +4,6 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageTypeEnum'] do
it 'exposes all package types' do
- expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER])
+ expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER GENERIC])
end
end
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
index fbe3473f6b0..15fa78444e5 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -176,6 +176,37 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
end
end
+ describe '#sorted' do
+ subject { test_suite.sorted }
+
+ context 'when there are multiple failed test cases' do
+ before do
+ test_suite.add_test_case(create_test_case_rspec_failed('test_spec_1', 1.11))
+ test_suite.add_test_case(create_test_case_rspec_failed('test_spec_2', 4.44))
+ end
+
+ it 'returns test cases sorted by execution time desc' do
+ expect(subject.test_cases['failed'].each_value.first.execution_time).to eq(4.44)
+ expect(subject.test_cases['failed'].values.second.execution_time).to eq(1.11)
+ end
+ end
+
+ context 'when there are multiple test cases' do
+ let(:status_ordered) { %w(error failed success skipped) }
+
+ before do
+ test_suite.add_test_case(test_case_success)
+ test_suite.add_test_case(test_case_failed)
+ test_suite.add_test_case(test_case_error)
+ test_suite.add_test_case(test_case_skipped)
+ end
+
+ it 'returns test cases sorted by status' do
+ expect(subject.test_cases.keys).to eq(status_ordered)
+ end
+ end
+ end
+
Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
describe "##{status_type}" do
subject { test_suite.public_send("#{status_type}") }
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 838667675c7..f736f19ca9a 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -426,4 +426,21 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('1.2') }
it { is_expected.not_to match('1./2.3') }
end
+
+ describe '.generic_package_version_regex' do
+ subject { described_class.generic_package_version_regex }
+
+ it { is_expected.to match('1.2.3') }
+ it { is_expected.to match('1.3.350') }
+ it { is_expected.not_to match('1.3.350-20201230123456') }
+ it { is_expected.not_to match('..1.2.3') }
+ it { is_expected.not_to match(' 1.2.3') }
+ it { is_expected.not_to match("1.2.3 \r\t") }
+ it { is_expected.not_to match("\r\t 1.2.3") }
+ it { is_expected.not_to match('1.2.3-4/../../') }
+ it { is_expected.not_to match('1.2.3-4%2e%2e%') }
+ it { is_expected.not_to match('../../../../../1.2.3') }
+ it { is_expected.not_to match('%2e%2e%2f1.2.3') }
+ it { is_expected.not_to match('') }
+ end
end
diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb
index 14f3bcc463e..716ab4d8522 100644
--- a/spec/models/ci/pipeline_artifact_spec.rb
+++ b/spec/models/ci/pipeline_artifact_spec.rb
@@ -109,4 +109,14 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
end
end
end
+
+ describe '#present' do
+ subject { coverage_report.present }
+
+ context 'when file_type is code_coverage' do
+ it 'uses code coverage presenter' do
+ expect(subject.present).to be_kind_of(Ci::PipelineArtifacts::CodeCoveragePresenter)
+ end
+ end
+ end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index da15b0f0453..4867ac2a75b 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -236,6 +236,25 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
+ context 'generic package' do
+ subject { build_stubbed(:generic_package) }
+
+ it { is_expected.to validate_presence_of(:version) }
+ it { is_expected.to allow_value('1.2.3').for(:version) }
+ it { is_expected.to allow_value('1.3.350').for(:version) }
+ it { is_expected.not_to allow_value('1.3.350-20201230123456').for(:version) }
+ it { is_expected.not_to allow_value('..1.2.3').for(:version) }
+ it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
+ it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
+ it { is_expected.not_to allow_value("\r\t 1.2.3").for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4/../../').for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4%2e%2e%').for(:version) }
+ it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('').for(:version) }
+ it { is_expected.not_to allow_value(nil).for(:version) }
+ end
+
it_behaves_like 'validating version to be SemVer compliant for', :npm_package
it_behaves_like 'validating version to be SemVer compliant for', :nuget_package
end
@@ -552,11 +571,17 @@ RSpec.describe Packages::Package, type: :model do
describe 'plan_limits' do
Packages::Package.package_types.keys.without('composer').each do |pt|
+ plan_limit_name = if pt == 'generic'
+ "#{pt}_packages_max_file_size"
+ else
+ "#{pt}_max_file_size"
+ end
+
context "File size limits for #{pt}" do
let(:package) { create("#{pt}_package") }
- it "plan_limits includes column #{pt}_max_file_size" do
- expect { package.project.actual_limits.send("#{pt}_max_file_size") }
+ it "plan_limits includes column #{plan_limit_name}" do
+ expect { package.project.actual_limits.send(plan_limit_name) }
.not_to raise_error(NoMethodError)
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/artifact/code_coverage_spec.rb b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb
index f3bc9fd0ec2..e679f5fa144 100644
--- a/spec/lib/gitlab/ci/pipeline/artifact/code_coverage_spec.rb
+++ b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb
@@ -2,12 +2,13 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Pipeline::Artifact::CodeCoverage do
+RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do
let(:pipeline_artifact) { create(:ci_pipeline_artifact, :with_code_coverage_with_multiple_files) }
- let(:code_coverage) { described_class.new(pipeline_artifact) }
+
+ subject(:presenter) { described_class.new(pipeline_artifact) }
describe '#for_files' do
- subject { code_coverage.for_files(filenames) }
+ subject { presenter.for_files(filenames) }
context 'when code coverage has data' do
context 'when filenames is empty' do
diff --git a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
index 5804b4b00fc..b769109057e 100644
--- a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
+++ b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
@@ -14,40 +14,120 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName, type: :ruboco
allow(cop).to receive(:in_migration?).and_return(true)
end
- context 'when indexes are configured with an options hash, but no name' do
- it 'registers an offense' do
- expect_offense(<<~RUBY)
- class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
+ context 'when creating complex indexes as part of create_table' do
+ context 'when indexes are configured with an options hash, but no name' do
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :test_table do |t|
+ t.integer :column1, null: false
+ t.integer :column2, null: false
+ t.jsonb :column3
+
+ t.index :column1, unique: true
+ t.index :column2, where: 'column1 = 0'
+ ^^^^^ #{described_class::MSG}
+ t.index :column3, using: :gin
+ ^^^^^ #{described_class::MSG}
+ end
+ end
+
+ def down
+ drop_table :test_table
+ end
+ end
+ RUBY
+
+ expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ end
+ end
+
+ context 'when indexes are configured with an options hash and name' do
+ it 'registers no offense' do
+ expect_no_offenses(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :test_table do |t|
+ t.integer :column1, null: false
+ t.integer :column2, null: false
+ t.jsonb :column3
+
+ t.index :column1, unique: true
+ t.index :column2, where: 'column1 = 0', name: 'my_index_1'
+ t.index :column3, using: :gin, name: 'my_gin_index'
+ end
+ end
+
+ def down
+ drop_table :test_table
+ end
+ end
+ RUBY
+ end
+ end
+ end
- INDEX_NAME = 'my_test_name'
+ context 'when indexes are added to an existing table' do
+ context 'when indexes are configured with an options hash, but no name' do
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
- disable_ddl_transaction!
+ disable_ddl_transaction!
- def up
- add_concurrent_index :test_indexes, :column1
+ def up
+ add_index :test_indexes, :column1
- add_concurrent_index :test_indexes, :column2, where: "column2 = 'value'", order: { column4: :desc }
- ^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ add_index :test_indexes, :column2, where: "column2 = 'value'", order: { column4: :desc }
+ ^^^^^^^^^ #{described_class::MSG}
+ end
- add_concurrent_index :test_indexes, :column3, where: 'column3 = 10', name: 'idx_equal_to_10'
+ def down
+ add_index :test_indexes, :column4, 'unique' => true, where: 'column4 IS NOT NULL'
+ ^^^^^^^^^ #{described_class::MSG}
+
+ add_concurrent_index :test_indexes, :column6, using: :gin, opclass: :gin_trgm_ops
+ ^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ end
end
+ RUBY
- def down
- add_concurrent_index :test_indexes, :column4, 'unique' => true
+ expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ end
+ end
- add_concurrent_index :test_indexes, :column4, 'unique' => true, where: 'column4 IS NOT NULL'
- ^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ context 'when indexes are configured with an options hash and a name' do
+ it 'registers no offenses' do
+ expect_no_offenses(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
- add_concurrent_index :test_indexes, :column5, using: :gin, name: INDEX_NAME
+ INDEX_NAME = 'my_test_name'
- add_concurrent_index :test_indexes, :column6, using: :gin, opclass: :gin_trgm_ops
- ^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
- end
- end
- RUBY
+ disable_ddl_transaction!
+
+ def up
+ add_index :test_indexes, :column1
+
+ add_index :test_indexes, :column2, where: "column2 = 'value'", order: { column4: :desc }, name: 'my_index_1'
+
+ add_concurrent_index :test_indexes, :column3, where: 'column3 = 10', name: 'idx_equal_to_10'
+ end
+
+ def down
+ add_index :test_indexes, :column4, 'unique' => true, where: 'column4 IS NOT NULL', name: 'my_index_2'
- expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ add_concurrent_index :test_indexes, :column6, using: :gin, opclass: :gin_trgm_ops, name: INDEX_NAME
+ end
+ end
+ RUBY
+ end
end
end
end
@@ -65,7 +145,13 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName, type: :ruboco
disable_ddl_transaction!
def up
- add_concurrent_index :test_indexes, :column1, where: "some_column = 'value'"
+ create_table :test_table do |t|
+ t.integer :column1
+
+ t.index :column1, where: 'column2 IS NOT NULL'
+ end
+
+ add_index :test_indexes, :column1, where: "some_column = 'value'"
end
def down
diff --git a/spec/services/ci/generate_coverage_reports_service_spec.rb b/spec/services/ci/generate_coverage_reports_service_spec.rb
index 722b92ea3b6..d39053adebc 100644
--- a/spec/services/ci/generate_coverage_reports_service_spec.rb
+++ b/spec/services/ci/generate_coverage_reports_service_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Ci::GenerateCoverageReportsService do
let!(:base_pipeline) { nil }
it 'returns status and data', :aggregate_failures do
- expect_next_instance_of(Gitlab::Ci::Pipeline::Artifact::CodeCoverage) do |instance|
+ expect_any_instance_of(Ci::PipelineArtifact) do |instance|
+ expect(instance).to receive(:present)
expect(instance).to receive(:for_files).with(merge_request.new_paths).and_call_original
end
diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb
index 45a4c2bb151..836997e78f5 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -161,6 +161,7 @@ RSpec.shared_examples 'filters on each package_type' do |is_project: false|
let_it_be(:package4) { create(:nuget_package, project: project) }
let_it_be(:package5) { create(:pypi_package, project: project) }
let_it_be(:package6) { create(:composer_package, project: project) }
+ let_it_be(:package7) { create(:generic_package, project: project) }
Packages::Package.package_types.keys.each do |package_type|
context "for package type #{package_type}" do
diff --git a/spec/support/test_reports/test_reports_helper.rb b/spec/support/test_reports/test_reports_helper.rb
index 6ba50c83b25..ad9ecb6f460 100644
--- a/spec/support/test_reports/test_reports_helper.rb
+++ b/spec/support/test_reports/test_reports_helper.rb
@@ -10,12 +10,12 @@ module TestReportsHelper
status: Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
end
- def create_test_case_rspec_failed(name = 'test_spec')
+ def create_test_case_rspec_failed(name = 'test_spec', execution_time = 2.22)
Gitlab::Ci::Reports::TestCase.new(
name: 'Test#sum when a is 1 and b is 3 returns summary',
classname: "spec.#{name}",
file: './spec/test_spec.rb',
- execution_time: 2.22,
+ execution_time: execution_time,
system_output: sample_rspec_failed_message,
status: Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
end