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-02-21 12:09:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-21 12:09:01 +0300
commita53d2c37c4934f564caa94543dd4cf5af1703e2d (patch)
treea028dc39771a4612a9845ab700a73af2d6f3f51b /spec
parent18b8435318887d3fc6e9f9d305967a953cdd7d3f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/navbar_spec.rb203
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js103
-rw-r--r--spec/frontend/frequent_items/mock_data.js9
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js94
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb9
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_spec.rb53
6 files changed, 286 insertions, 185 deletions
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index bcb05e1c718..4ab6b0ce506 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -3,102 +3,123 @@
require 'spec_helper'
describe 'Project navbar' do
- it_behaves_like 'verified navigation bar' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
- let(:structure) do
- [
- {
- nav_item: _('Project overview'),
- nav_sub_items: [
- _('Details'),
- _('Activity'),
- _('Releases')
- ]
- },
- {
- nav_item: _('Repository'),
- nav_sub_items: [
- _('Files'),
- _('Commits'),
- _('Branches'),
- _('Tags'),
- _('Contributors'),
- _('Graph'),
- _('Compare'),
- (_('Locked Files') if Gitlab.ee?)
- ]
- },
- {
- nav_item: _('Issues'),
- nav_sub_items: [
- _('List'),
- _('Boards'),
- _('Labels'),
- _('Milestones')
- ]
- },
- {
- nav_item: _('Merge Requests'),
- nav_sub_items: []
- },
- {
- nav_item: _('CI / CD'),
- nav_sub_items: [
- _('Pipelines'),
- _('Jobs'),
- _('Artifacts'),
- _('Schedules')
- ]
- },
- {
- nav_item: _('Operations'),
- nav_sub_items: [
- _('Metrics'),
- _('Environments'),
- _('Error Tracking'),
- _('Serverless'),
- _('Kubernetes')
- ]
- },
- {
- nav_item: _('Analytics'),
- nav_sub_items: [
- _('CI / CD Analytics'),
- (_('Code Review') if Gitlab.ee?),
- _('Repository Analytics'),
- _('Value Stream Analytics')
- ]
- },
- {
- nav_item: _('Wiki'),
- nav_sub_items: []
- },
- {
- nav_item: _('Snippets'),
- nav_sub_items: []
- },
- {
- nav_item: _('Settings'),
- nav_sub_items: [
- _('General'),
- _('Members'),
- _('Integrations'),
- _('Repository'),
- _('CI / CD'),
- _('Operations'),
- (_('Audit Events') if Gitlab.ee?)
- ].compact
- }
+ let(:analytics_nav_item) do
+ {
+ nav_item: _('Analytics'),
+ nav_sub_items: [
+ _('CI / CD Analytics'),
+ (_('Code Review') if Gitlab.ee?),
+ _('Repository Analytics'),
+ _('Value Stream Analytics')
]
- end
+ }
+ end
- before do
- project.add_maintainer(user)
- sign_in(user)
+ let(:structure) do
+ [
+ {
+ nav_item: _('Project overview'),
+ nav_sub_items: [
+ _('Details'),
+ _('Activity'),
+ _('Releases')
+ ]
+ },
+ {
+ nav_item: _('Repository'),
+ nav_sub_items: [
+ _('Files'),
+ _('Commits'),
+ _('Branches'),
+ _('Tags'),
+ _('Contributors'),
+ _('Graph'),
+ _('Compare'),
+ (_('Locked Files') if Gitlab.ee?)
+ ]
+ },
+ {
+ nav_item: _('Issues'),
+ nav_sub_items: [
+ _('List'),
+ _('Boards'),
+ _('Labels'),
+ _('Milestones')
+ ]
+ },
+ {
+ nav_item: _('Merge Requests'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('CI / CD'),
+ nav_sub_items: [
+ _('Pipelines'),
+ _('Jobs'),
+ _('Artifacts'),
+ _('Schedules')
+ ]
+ },
+ {
+ nav_item: _('Operations'),
+ nav_sub_items: [
+ _('Metrics'),
+ _('Environments'),
+ _('Error Tracking'),
+ _('Serverless'),
+ _('Kubernetes')
+ ]
+ },
+ analytics_nav_item,
+ {
+ nav_item: _('Wiki'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Snippets'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Settings'),
+ nav_sub_items: [
+ _('General'),
+ _('Members'),
+ _('Integrations'),
+ _('Repository'),
+ _('CI / CD'),
+ _('Operations'),
+ (_('Audit Events') if Gitlab.ee?)
+ ].compact
+ }
+ ]
+ end
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+ it_behaves_like 'verified navigation bar' do
+ before do
visit project_path(project)
end
end
+
+ if Gitlab.ee?
+ context 'when issues analytics is available' do
+ before do
+ stub_licensed_features(issues_analytics: true)
+
+ analytics_nav_item[:nav_sub_items] << _('Issues Analytics')
+ analytics_nav_item[:nav_sub_items].sort!
+
+ visit project_path(project)
+ end
+
+ it_behaves_like 'verified navigation bar'
+ end
+ end
end
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
new file mode 100644
index 00000000000..925699f5623
--- /dev/null
+++ b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
@@ -0,0 +1,103 @@
+import { shallowMount } from '@vue/test-utils';
+import { trimText } from 'helpers/text_helper';
+import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
+import mockData from '../mock_data'; // can also use 'mockGroup', but not useful to test here
+
+const mockProject = mockData();
+
+describe('FrequentItemsListItemComponent', () => {
+ let wrapper;
+
+ const findTitle = () => wrapper.find({ ref: 'frequentItemsItemTitle' });
+ const findAvatar = () => wrapper.find({ ref: 'frequentItemsItemAvatar' });
+ const findAllTitles = () => wrapper.findAll({ ref: 'frequentItemsItemTitle' });
+ const findNamespace = () => wrapper.find({ ref: 'frequentItemsItemNamespace' });
+ const findAllAnchors = () => wrapper.findAll('a');
+ const findAllNamespace = () => wrapper.findAll({ ref: 'frequentItemsItemNamespace' });
+ const findAvatarContainer = () => wrapper.findAll({ ref: 'frequentItemsItemAvatarContainer' });
+ const findAllMetadataContainers = () =>
+ wrapper.findAll({ ref: 'frequentItemsItemMetadataContainer' });
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(frequentItemsListItemComponent, {
+ propsData: {
+ itemId: mockProject.id,
+ itemName: mockProject.name,
+ namespace: mockProject.namespace,
+ webUrl: mockProject.webUrl,
+ avatarUrl: mockProject.avatarUrl,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('computed', () => {
+ describe('highlightedItemName', () => {
+ it('should enclose part of project name in <b> & </b> which matches with `matcher` prop', () => {
+ createComponent({ matcher: 'lab' });
+
+ expect(findTitle().element.innerHTML).toContain('<b>L</b><b>a</b><b>b</b>');
+ });
+
+ it('should return project name as it is if `matcher` is not available', () => {
+ createComponent({ matcher: null });
+
+ expect(trimText(findTitle().text())).toBe(mockProject.name);
+ });
+ });
+
+ describe('truncatedNamespace', () => {
+ it('should truncate project name from namespace string', () => {
+ createComponent({ namespace: 'platform / nokia-3310' });
+
+ expect(trimText(findNamespace().text())).toBe('platform');
+ });
+
+ it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
+ createComponent({
+ namespace: 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310',
+ });
+
+ expect(trimText(findNamespace().text())).toBe('platform / ... / Mobile Chipset');
+ });
+ });
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should render avatar if avatarUrl is present', () => {
+ wrapper.setProps({ avatarUrl: 'path/to/avatar.png' });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(findAvatar().exists()).toBe(true);
+ });
+ });
+
+ it('should not render avatar if avatarUrl is not present', () => {
+ expect(findAvatar().exists()).toBe(false);
+ });
+
+ it('renders root element with the right classes', () => {
+ expect(wrapper.classes('frequent-items-list-item-container')).toBe(true);
+ });
+
+ it.each`
+ name | selector | expected
+ ${'anchor'} | ${findAllAnchors} | ${1}
+ ${'avatar container'} | ${findAvatarContainer} | ${1}
+ ${'metadata container'} | ${findAllMetadataContainers} | ${1}
+ ${'title'} | ${findAllTitles} | ${1}
+ ${'namespace'} | ${findAllNamespace} | ${1}
+ `('should render $expected $name', ({ selector, expected }) => {
+ expect(selector()).toHaveLength(expected);
+ });
+ });
+});
diff --git a/spec/frontend/frequent_items/mock_data.js b/spec/frontend/frequent_items/mock_data.js
new file mode 100644
index 00000000000..81f34053543
--- /dev/null
+++ b/spec/frontend/frequent_items/mock_data.js
@@ -0,0 +1,9 @@
+import { TEST_HOST } from 'helpers/test_constants';
+
+export default () => ({
+ id: 1,
+ name: 'GitLab Community Edition',
+ namespace: 'gitlab-org / gitlab-ce',
+ webUrl: `${TEST_HOST}/gitlab-org/gitlab-foss`,
+ avatarUrl: null,
+});
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
deleted file mode 100644
index e3f05e89a2d..00000000000
--- a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/text_helper';
-import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
-import { mockProject } from '../mock_data'; // can also use 'mockGroup', but not useful to test here
-
-const localVue = createLocalVue();
-
-describe('FrequentItemsListItemComponent', () => {
- let wrapper;
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(localVue.extend(frequentItemsListItemComponent), {
- propsData: {
- itemId: mockProject.id,
- itemName: mockProject.name,
- namespace: mockProject.namespace,
- webUrl: mockProject.webUrl,
- avatarUrl: mockProject.avatarUrl,
- ...props,
- },
- localVue,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('computed', () => {
- describe('hasAvatar', () => {
- it('should return `true` or `false` if whether avatar is present or not', () => {
- createComponent({ avatarUrl: 'path/to/avatar.png' });
-
- expect(wrapper.vm.hasAvatar).toBe(true);
- });
-
- it('should return `false` if avatar is not present', () => {
- createComponent({ avatarUrl: null });
-
- expect(wrapper.vm.hasAvatar).toBe(false);
- });
- });
-
- describe('highlightedItemName', () => {
- it('should enclose part of project name in <b> & </b> which matches with `matcher` prop', () => {
- createComponent({ matcher: 'lab' });
-
- expect(wrapper.find('.js-frequent-items-item-title').html()).toContain(
- '<b>L</b><b>a</b><b>b</b>',
- );
- });
-
- it('should return project name as it is if `matcher` is not available', () => {
- createComponent({ matcher: null });
-
- expect(trimText(wrapper.find('.js-frequent-items-item-title').text())).toBe(
- mockProject.name,
- );
- });
- });
-
- describe('truncatedNamespace', () => {
- it('should truncate project name from namespace string', () => {
- createComponent({ namespace: 'platform / nokia-3310' });
-
- expect(trimText(wrapper.find('.js-frequent-items-item-namespace').text())).toBe('platform');
- });
-
- it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
- createComponent({
- namespace: 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310',
- });
-
- expect(trimText(wrapper.find('.js-frequent-items-item-namespace').text())).toBe(
- 'platform / ... / Mobile Chipset',
- );
- });
- });
- });
-
- describe('template', () => {
- it('should render component element', () => {
- createComponent();
-
- expect(wrapper.classes()).toContain('frequent-items-list-item-container');
- expect(wrapper.findAll('a').length).toBe(1);
- expect(wrapper.findAll('.frequent-items-item-avatar-container').length).toBe(1);
- expect(wrapper.findAll('.frequent-items-item-metadata-container').length).toBe(1);
- expect(wrapper.findAll('.frequent-items-item-title').length).toBe(1);
- expect(wrapper.findAll('.frequent-items-item-namespace').length).toBe(1);
- });
- });
-});
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index bb5475130cf..ce6e8c731e2 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -1332,6 +1332,15 @@ describe Gitlab::Database::MigrationHelpers do
end
end
end
+
+ context 'with other_arguments option' do
+ it 'queues jobs correctly' do
+ model.queue_background_migration_jobs_by_range_at_intervals(User, 'FooJob', 10.minutes, other_arguments: [1, 2])
+
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['FooJob', [id1, id3, 1, 2]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to eq(10.minutes.from_now.to_f)
+ end
+ end
end
context "when the model doesn't have an ID column" do
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
new file mode 100644
index 00000000000..bec8435b2f0
--- /dev/null
+++ b/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200128210353_cleanup_optimistic_locking_nulls')
+
+describe CleanupOptimisticLockingNulls, :migration do
+ TABLES = %w(epics merge_requests issues).freeze
+ TABLES.each do |table|
+ let(table.to_sym) { table(table.to_sym) }
+ end
+ let(:tables) { TABLES.map { |t| method(t.to_sym).call } }
+
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users)}
+
+ before do
+ namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
+ users.create!(id: 123, username: 'author', projects_limit: 1000)
+
+ # Create necessary rows
+ epics.create!(iid: 123, group_id: 123, author_id: 123, title: 'a', title_html: 'a')
+ merge_requests.create!(iid: 123, target_project_id: 123, source_project_id: 123, target_branch: 'master', source_branch: 'hmm', title: 'a', title_html: 'a')
+ issues.create!(iid: 123, project_id: 123, title: 'a', title_html: 'a')
+
+ # Nullify `lock_version` column for all rows
+ # Needs to be done with a SQL fragment, otherwise Rails will coerce it to 0
+ tables.each do |table|
+ table.update_all('lock_version = NULL')
+ end
+ end
+
+ it 'correctly migrates nullified lock_version column', :sidekiq_inline do
+ tables.each do |table|
+ expect(table.where(lock_version: nil).count).to eq(1)
+ end
+
+ tables.each do |table|
+ expect(table.where(lock_version: 0).count).to eq(0)
+ end
+
+ migrate!
+
+ tables.each do |table|
+ expect(table.where(lock_version: nil).count).to eq(0)
+ end
+
+ tables.each do |table|
+ expect(table.where(lock_version: 0).count).to eq(1)
+ end
+ end
+end