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>2023-01-16 18:07:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-16 18:07:37 +0300
commitf0718f2099663226531b8916e14d5582eb28e453 (patch)
treebd8f8e6ef6353b1ce066c43c0e19655ca3be62e6 /spec
parent6d4ce68742e8decbfca5a1b382ce260790e8c396 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/commands/sidekiq_cluster/cli_spec.rb12
-rw-r--r--spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb12
-rw-r--r--spec/features/projects/files/template_type_dropdown_spec.rb143
-rw-r--r--spec/features/projects/files/undo_template_spec.rb19
-rw-r--r--spec/features/snippets/show_spec.rb7
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js62
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js49
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_spec.js35
-rw-r--r--spec/frontend/frequent_items/store/actions_spec.js87
-rw-r--r--spec/frontend/frequent_items/store/mutations_spec.js35
-rw-r--r--spec/lib/gitlab/database/tables_truncate_spec.rb35
-rw-r--r--spec/views/layouts/snippets.html.haml_spec.rb36
12 files changed, 300 insertions, 232 deletions
diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb
index 75361686f14..0c32fa2571a 100644
--- a/spec/commands/sidekiq_cluster/cli_spec.rb
+++ b/spec/commands/sidekiq_cluster/cli_spec.rb
@@ -245,9 +245,15 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
it 'expands multiple queue groups correctly' do
expected_workers =
if Gitlab.ee?
- [%w[], %w[project_export projects_import_export_parallel_project_export projects_import_export_relation_export project_template_export]]
+ [
+ %w[cronjob:clusters_integrations_check_prometheus_health incident_management_close_incident status_page_publish],
+ %w[project_export projects_import_export_parallel_project_export projects_import_export_relation_export project_template_export]
+ ]
else
- [%w[], %w[project_export projects_import_export_parallel_project_export projects_import_export_relation_export]]
+ [
+ %w[cronjob:clusters_integrations_check_prometheus_health incident_management_close_incident],
+ %w[project_export projects_import_export_parallel_project_export projects_import_export_relation_export]
+ ]
end
expect(Gitlab::SidekiqCluster)
@@ -255,7 +261,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
.with(expected_workers, default_options)
.and_return([])
- cli.run(%w(--queue-selector feature_category=continuous_integration&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
+ cli.run(%w(--queue-selector feature_category=incident_management&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
end
it 'allows the special * selector' do
diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
index a497be4cbc3..b723bd5690a 100644
--- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
+++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
@@ -24,12 +24,6 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled
expect(file_name.value).to have_content('.gitlab-ci.yml')
end
- it 'chooses the .gitlab-ci.yml Template Type' do
- template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
-
- expect(template_type.text).to have_content('.gitlab-ci.yml')
- end
-
it 'displays suggest_gitlab_ci_yml popover' do
page.find(:css, '.gitlab-ci-yml-selector').click
@@ -60,12 +54,6 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled
expect(file_name.value).not_to have_content('.gitlab-ci.yml')
end
- it 'does not choose the .gitlab-ci.yml Template Type' do
- template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
-
- expect(template_type.text).to have_content('Select a template type')
- end
-
it 'does not display suggest_gitlab_ci_yml popover' do
popover_selector = '.b-popover.suggest-gitlab-ci-yml'
diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb
deleted file mode 100644
index 990b118d172..00000000000
--- a/spec/features/projects/files/template_type_dropdown_spec.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > Template type dropdown selector', :js, feature_category: :projects do
- let(:project) { create(:project, :repository) }
- let(:user) { project.first_owner }
-
- before do
- sign_in user
- end
-
- context 'editing a non-matching file' do
- before do
- create_and_edit_file('.random-file.js')
- end
-
- it 'not displayed' do
- check_type_selector_display(false)
- end
-
- it 'selects every template type correctly' do
- fill_in 'file_path', with: '.gitignore'
- try_selecting_all_types
- end
-
- it 'updates template type toggle value when template is chosen' do
- fill_in 'file_path', with: '.gitignore'
- select_template('gitignore', 'Actionscript')
- check_type_selector_toggle_text('.gitignore')
- end
- end
-
- context 'editing a matching file' do
- before do
- visit project_edit_blob_path(project, File.join(project.default_branch, 'LICENSE'))
- end
-
- it 'displayed' do
- check_type_selector_display(true)
- end
-
- it 'selects every template type correctly' do
- try_selecting_all_types
- end
-
- context 'user previews changes' do
- before do
- click_link 'Preview changes'
- end
-
- it 'type selector is hidden and shown correctly' do
- check_type_selector_display(false)
- click_link 'Write'
- check_type_selector_display(true)
- end
- end
- end
-
- context 'creating a matching file' do
- before do
- visit project_new_blob_path(project, 'master', file_name: '.gitignore')
- end
-
- it 'is displayed' do
- check_type_selector_display(true)
- end
-
- it 'toggle is set to the correct value' do
- select_template('gitignore', 'Actionscript')
- check_type_selector_toggle_text('.gitignore')
- end
-
- it 'sets the toggle text when selecting the template type' do
- select_template_type('.gitignore')
- check_type_selector_toggle_text('.gitignore')
- end
-
- it 'selects every template type correctly' do
- try_selecting_all_types
- end
- end
-
- context 'creating a file' do
- before do
- visit project_new_blob_path(project, project.default_branch)
- end
-
- it 'type selector is shown' do
- check_type_selector_display(true)
- end
-
- it 'toggle is set to the proper value' do
- check_type_selector_toggle_text('Select a template type')
- end
-
- it 'selects every template type correctly' do
- try_selecting_all_types
- end
- end
-end
-
-def check_type_selector_display(is_visible)
- count = is_visible ? 1 : 0
- expect(page).to have_css('.js-template-type-selector', count: count)
-end
-
-def try_selecting_all_types
- try_selecting_template_type('LICENSE', 'Apply a template')
- try_selecting_template_type('Dockerfile', 'Apply a template')
- try_selecting_template_type('.gitlab-ci.yml', 'Apply a template')
- try_selecting_template_type('.gitignore', 'Apply a template')
-end
-
-def try_selecting_template_type(template_type, selector_label)
- select_template_type(template_type)
- check_template_selector_display(selector_label)
-end
-
-def select_template_type(template_type)
- find('.js-template-type-selector').click
- find('.dropdown-content li', text: template_type).click
-end
-
-def select_template(type, template)
- find(".js-#{type}-selector-wrap").click
- find('.dropdown-content li', text: template).click
-end
-
-def check_template_selector_display(content)
- expect(page).to have_content(content)
-end
-
-def check_type_selector_toggle_text(template_type)
- dropdown_toggle_button = find('.template-type-selector .dropdown-toggle-text')
- expect(dropdown_toggle_button).to have_content(template_type)
-end
-
-def create_and_edit_file(file_name)
- visit project_new_blob_path(project, 'master', file_name: file_name)
- click_button "Commit changes"
- visit project_edit_blob_path(project, File.join(project.default_branch, file_name))
-end
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index afc9a5fd232..0dfed209ce9 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -13,19 +13,6 @@ RSpec.describe 'Projects > Files > Template Undo Button', :js, feature_category:
context 'editing a matching file and applying a template' do
before do
visit project_edit_blob_path(project, File.join(project.default_branch, "LICENSE"))
- select_file_template_type('LICENSE')
- select_file_template('.js-license-selector', 'Apache License 2.0')
- end
-
- it 'reverts template application' do
- try_template_undo('http://www.apache.org/licenses/', 'Apply a template')
- end
- end
-
- context 'creating a non-matching file' do
- before do
- visit project_new_blob_path(project, 'master')
- select_file_template_type('LICENSE')
select_file_template('.js-license-selector', 'Apache License 2.0')
end
@@ -53,7 +40,6 @@ end
def check_content_reverted(template_content)
find('.b-toaster a', text: 'Undo').click
expect(page).not_to have_content(template_content)
- expect(page).to have_css('.template-type-selector .dropdown-toggle-text')
end
def select_file_template(template_selector_selector, template_name)
@@ -61,8 +47,3 @@ def select_file_template(template_selector_selector, template_name)
find('.dropdown-content li', text: template_name).click
wait_for_requests
end
-
-def select_file_template_type(template_type)
- find('.js-template-type-selector').click
- find('.dropdown-content li', text: template_type).click
-end
diff --git a/spec/features/snippets/show_spec.rb b/spec/features/snippets/show_spec.rb
index 2870f729765..dc2fcdd7305 100644
--- a/spec/features/snippets/show_spec.rb
+++ b/spec/features/snippets/show_spec.rb
@@ -43,11 +43,6 @@ RSpec.describe 'Snippet', :js, feature_category: :source_code_management do
sign_in(different_user)
end
- it 'does not have the sidebar' do
- visit snippet_path(snippet)
-
- expect(page).to have_title _('Snippets')
- expect(page).not_to have_css('aside.nav-sidebar')
- end
+ it_behaves_like 'a dashboard page with sidebar', :dashboard_snippets_path, :snippets
end
end
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index c201bbf4af2..b1e87aca63d 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -1,3 +1,4 @@
+import { GlButton, GlIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
@@ -103,6 +104,7 @@ describe('Frequent Items App Component', () => {
expect(loading.exists()).toBe(true);
expect(loading.find('[aria-label="Loading projects"]').exists()).toBe(true);
+ expect(findSectionHeader().exists()).toBe(false);
});
it('should render frequent projects list header', () => {
@@ -112,25 +114,6 @@ describe('Frequent Items App Component', () => {
expect(sectionHeader.text()).toBe('Frequently visited');
});
- it('should render frequent projects list', async () => {
- const expectedResult = getTopFrequentItems(mockFrequentProjects);
- localStorage.setItem(TEST_STORAGE_KEY, JSON.stringify(mockFrequentProjects));
-
- expect(findFrequentItems().length).toBe(1);
-
- triggerDropdownOpen();
- await nextTick();
-
- expect(findFrequentItems().length).toBe(expectedResult.length);
- expect(findFrequentItemsList().props()).toEqual({
- items: expectedResult,
- namespace: TEST_NAMESPACE,
- hasSearchQuery: false,
- isFetchFailed: false,
- matcher: '',
- });
- });
-
it('should render searched projects list', async () => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects.data);
@@ -164,6 +147,47 @@ describe('Frequent Items App Component', () => {
}),
);
});
+
+ describe('with frequent items list', () => {
+ const expectedResult = getTopFrequentItems(mockFrequentProjects);
+
+ beforeEach(async () => {
+ localStorage.setItem(TEST_STORAGE_KEY, JSON.stringify(mockFrequentProjects));
+ triggerDropdownOpen();
+ await nextTick();
+ });
+
+ it('should render edit button within header', () => {
+ const itemEditButton = findSectionHeader().findComponent(GlButton);
+
+ expect(itemEditButton.exists()).toBe(true);
+ expect(itemEditButton.attributes('title')).toBe('Toggle edit mode');
+ expect(itemEditButton.findComponent(GlIcon).props('name')).toBe('pencil');
+ });
+
+ it('should render frequent projects list', () => {
+ expect(findFrequentItems().length).toBe(expectedResult.length);
+ expect(findFrequentItemsList().props()).toEqual({
+ items: expectedResult,
+ namespace: TEST_NAMESPACE,
+ hasSearchQuery: false,
+ isFetchFailed: false,
+ isItemRemovalFailed: false,
+ matcher: '',
+ });
+ });
+
+ it('dispatches action `toggleItemsListEditablity` when edit button is clicked', async () => {
+ const itemEditButton = findSectionHeader().findComponent(GlButton);
+ itemEditButton.vm.$emit('click');
+
+ await nextTick();
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ `${TEST_VUEX_MODULE}/toggleItemsListEditablity`,
+ );
+ });
+ });
});
describe('with searchClass', () => {
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
index e6673fa78ec..4f2badf869d 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,5 +1,5 @@
-import { GlButton } from '@gitlab/ui';
-import Vue from 'vue';
+import { GlIcon } from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { trimText } from 'helpers/text_helper';
@@ -12,6 +12,7 @@ import { mockProject } from '../mock_data';
Vue.use(Vuex);
describe('FrequentItemsListItemComponent', () => {
+ const TEST_VUEX_MODULE = 'frequentProjects';
let wrapper;
let trackingSpy;
let store;
@@ -20,11 +21,18 @@ describe('FrequentItemsListItemComponent', () => {
const findAvatar = () => wrapper.findComponent(ProjectAvatar);
const findAllTitles = () => wrapper.findAllByTestId('frequent-items-item-title');
const findNamespace = () => wrapper.findByTestId('frequent-items-item-namespace');
- const findAllButtons = () => wrapper.findAllComponents(GlButton);
+ const findAllFrequentItems = () => wrapper.findAllByTestId('frequent-item-link');
const findAllNamespace = () => wrapper.findAllByTestId('frequent-items-item-namespace');
const findAllAvatars = () => wrapper.findAllComponents(ProjectAvatar);
const findAllMetadataContainers = () =>
wrapper.findAllByTestId('frequent-items-item-metadata-container');
+ const findRemoveButton = () => wrapper.findByTestId('item-remove');
+
+ const toggleItemsListEditablity = async () => {
+ store.dispatch(`${TEST_VUEX_MODULE}/toggleItemsListEditablity`);
+
+ await nextTick();
+ };
const createComponent = (props = {}) => {
wrapper = shallowMountExtended(frequentItemsListItemComponent, {
@@ -38,7 +46,7 @@ describe('FrequentItemsListItemComponent', () => {
...props,
},
provide: {
- vuexModule: 'frequentProjects',
+ vuexModule: TEST_VUEX_MODULE,
},
});
};
@@ -102,7 +110,7 @@ describe('FrequentItemsListItemComponent', () => {
it.each`
name | selector | expected
- ${'button'} | ${findAllButtons} | ${1}
+ ${'list item'} | ${findAllFrequentItems} | ${1}
${'avatar container'} | ${findAllAvatars} | ${1}
${'metadata container'} | ${findAllMetadataContainers} | ${1}
${'title'} | ${findAllTitles} | ${1}
@@ -111,8 +119,37 @@ describe('FrequentItemsListItemComponent', () => {
expect(selector()).toHaveLength(expected);
});
+ it('renders remove button within item when `isItemsListEditable` is true', async () => {
+ await toggleItemsListEditablity();
+
+ const removeButton = findRemoveButton();
+ expect(removeButton.exists()).toBe(true);
+ expect(removeButton.attributes('title')).toBe('Remove');
+ expect(removeButton.findComponent(GlIcon).props('name')).toBe('close');
+ });
+
+ it('dispatches action `removeFrequentItem` when remove button is clicked', async () => {
+ await toggleItemsListEditablity();
+
+ jest.spyOn(store, 'dispatch');
+
+ const removeButton = findRemoveButton();
+ removeButton.vm.$emit(
+ 'click',
+ { stopPropagation: jest.fn(), preventDefault: jest.fn() },
+ mockProject.id,
+ );
+
+ await nextTick();
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ `${TEST_VUEX_MODULE}/removeFrequentItem`,
+ mockProject.id,
+ );
+ });
+
it('tracks when item link is clicked', () => {
- const link = wrapper.findComponent(GlButton);
+ const link = wrapper.findByTestId('frequent-item-link');
link.vm.$emit('click');
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
index 9f08a432a3d..d024925f62b 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
@@ -18,6 +18,7 @@ describe('FrequentItemsListComponent', () => {
namespace: 'projects',
items: mockFrequentProjects,
isFetchFailed: false,
+ isItemRemovalFailed: false,
hasSearchQuery: false,
matcher: 'lab',
...props,
@@ -51,22 +52,34 @@ describe('FrequentItemsListComponent', () => {
});
describe('fetched item messages', () => {
- it('should return appropriate empty list message based on value of `localStorageFailed` prop with projects', async () => {
+ it('should show default empty list message', async () => {
createComponent({
- isFetchFailed: true,
+ items: [],
});
- expect(wrapper.vm.listEmptyMessage).toBe(
- 'This feature requires browser localStorage support',
+ expect(wrapper.findByTestId('frequent-items-list-empty').text()).toContain(
+ 'Projects you visit often will appear here',
);
-
- wrapper.setProps({
- isFetchFailed: false,
- });
- await nextTick();
-
- expect(wrapper.vm.listEmptyMessage).toBe('Projects you visit often will appear here');
});
+
+ it.each`
+ isFetchFailed | isItemRemovalFailed
+ ${true} | ${false}
+ ${false} | ${true}
+ `(
+ 'should show failure message when `isFetchFailed` is $isFetchFailed or `isItemRemovalFailed` is $isItemRemovalFailed',
+ ({ isFetchFailed, isItemRemovalFailed }) => {
+ createComponent({
+ items: [],
+ isFetchFailed,
+ isItemRemovalFailed,
+ });
+
+ expect(wrapper.findByTestId('frequent-items-list-empty').text()).toContain(
+ 'This feature requires browser localStorage support',
+ );
+ },
+ );
});
describe('searched item messages', () => {
diff --git a/spec/frontend/frequent_items/store/actions_spec.js b/spec/frontend/frequent_items/store/actions_spec.js
index 3fc3eaf52a2..4f998cc26da 100644
--- a/spec/frontend/frequent_items/store/actions_spec.js
+++ b/spec/frontend/frequent_items/store/actions_spec.js
@@ -5,6 +5,7 @@ import * as types from '~/frequent_items/store/mutation_types';
import state from '~/frequent_items/store/state';
import AccessorUtilities from '~/lib/utils/accessor';
import axios from '~/lib/utils/axios_utils';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import {
mockNamespace,
mockStorageKey,
@@ -13,6 +14,7 @@ import {
} from '../mock_data';
describe('Frequent Items Dropdown Store Actions', () => {
+ useLocalStorageSpy();
let mockedState;
let mock;
@@ -52,6 +54,18 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
});
+ describe('toggleItemsListEditablity', () => {
+ it('should toggle items list editablity', () => {
+ return testAction(
+ actions.toggleItemsListEditablity,
+ null,
+ mockedState,
+ [{ type: types.TOGGLE_ITEMS_LIST_EDITABILITY }],
+ [],
+ );
+ });
+ });
+
describe('requestFrequentItems', () => {
it('should request frequent items', () => {
return testAction(
@@ -211,4 +225,77 @@ describe('Frequent Items Dropdown Store Actions', () => {
);
});
});
+
+ describe('removeFrequentItemSuccess', () => {
+ it('should remove frequent item on success', () => {
+ return testAction(
+ actions.removeFrequentItemSuccess,
+ { itemId: 1 },
+ mockedState,
+ [
+ {
+ type: types.RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS,
+ payload: { itemId: 1 },
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('removeFrequentItemError', () => {
+ it('should should not remove frequent item on failure', () => {
+ return testAction(
+ actions.removeFrequentItemError,
+ null,
+ mockedState,
+ [{ type: types.RECEIVE_REMOVE_FREQUENT_ITEM_ERROR }],
+ [],
+ );
+ });
+ });
+
+ describe('removeFrequentItem', () => {
+ beforeEach(() => {
+ mockedState.items = [...mockFrequentProjects];
+ window.localStorage.setItem(mockStorageKey, JSON.stringify(mockFrequentProjects));
+ });
+
+ it('should remove provided itemId from localStorage', () => {
+ jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(true);
+
+ actions.removeFrequentItem(
+ { commit: jest.fn(), dispatch: jest.fn(), state: mockedState },
+ mockFrequentProjects[0].id,
+ );
+
+ expect(window.localStorage.getItem(mockStorageKey)).toBe(
+ JSON.stringify(mockFrequentProjects.slice(1)), // First item was removed
+ );
+ });
+
+ it('should dispatch `removeFrequentItemSuccess` on localStorage update success', () => {
+ jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(true);
+
+ return testAction(
+ actions.removeFrequentItem,
+ mockFrequentProjects[0].id,
+ mockedState,
+ [],
+ [{ type: 'removeFrequentItemSuccess', payload: mockFrequentProjects[0].id }],
+ );
+ });
+
+ it('should dispatch `removeFrequentItemError` on localStorage update failure', () => {
+ jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(false);
+
+ return testAction(
+ actions.removeFrequentItem,
+ mockFrequentProjects[0].id,
+ mockedState,
+ [],
+ [{ type: 'removeFrequentItemError' }],
+ );
+ });
+ });
});
diff --git a/spec/frontend/frequent_items/store/mutations_spec.js b/spec/frontend/frequent_items/store/mutations_spec.js
index e593c9fae58..1e1878c3377 100644
--- a/spec/frontend/frequent_items/store/mutations_spec.js
+++ b/spec/frontend/frequent_items/store/mutations_spec.js
@@ -44,6 +44,18 @@ describe('Frequent Items dropdown mutations', () => {
});
});
+ describe('TOGGLE_ITEMS_LIST_EDITABILITY', () => {
+ it('should toggle items list editablity', () => {
+ mutations[types.TOGGLE_ITEMS_LIST_EDITABILITY](stateCopy);
+
+ expect(stateCopy.isItemsListEditable).toEqual(true);
+
+ mutations[types.TOGGLE_ITEMS_LIST_EDITABILITY](stateCopy);
+
+ expect(stateCopy.isItemsListEditable).toEqual(false);
+ });
+ });
+
describe('REQUEST_FREQUENT_ITEMS', () => {
it('should set view states when requesting frequent items', () => {
mutations[types.REQUEST_FREQUENT_ITEMS](stateCopy);
@@ -114,4 +126,27 @@ describe('Frequent Items dropdown mutations', () => {
expect(stateCopy.isFetchFailed).toEqual(true);
});
});
+
+ describe('RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS', () => {
+ it('should remove item with provided itemId from the items', () => {
+ stateCopy.isItemRemovalFailed = true;
+ stateCopy.items = mockFrequentProjects;
+
+ mutations[types.RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS](stateCopy, mockFrequentProjects[0].id);
+
+ expect(stateCopy.items).toHaveLength(mockFrequentProjects.length - 1);
+ expect(stateCopy.items).toEqual([...mockFrequentProjects.slice(1)]);
+ expect(stateCopy.isItemRemovalFailed).toBe(false);
+ });
+ });
+
+ describe('RECEIVE_REMOVE_FREQUENT_ITEM_ERROR', () => {
+ it('should remove item with provided itemId from the items', () => {
+ stateCopy.isItemRemovalFailed = false;
+
+ mutations[types.RECEIVE_REMOVE_FREQUENT_ITEM_ERROR](stateCopy);
+
+ expect(stateCopy.isItemRemovalFailed).toBe(true);
+ });
+ });
});
diff --git a/spec/lib/gitlab/database/tables_truncate_spec.rb b/spec/lib/gitlab/database/tables_truncate_spec.rb
index dc719679449..9af0b964221 100644
--- a/spec/lib/gitlab/database/tables_truncate_spec.rb
+++ b/spec/lib/gitlab/database/tables_truncate_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
let(:main_db_shared_item_model) { table("_test_gitlab_shared_items", database: "main") }
let(:main_db_partitioned_item) { table("_test_gitlab_hook_logs", database: "main") }
let(:main_db_partitioned_item_detached) do
- table("gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101", database: "main")
+ table("gitlab_partitions_dynamic._test_gitlab_hook_logs_202201", database: "main")
end
# CI Database
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
let(:ci_db_shared_item_model) { table("_test_gitlab_shared_items", database: "ci") }
let(:ci_db_partitioned_item) { table("_test_gitlab_hook_logs", database: "ci") }
let(:ci_db_partitioned_item_detached) do
- table("gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101", database: "ci")
+ table("gitlab_partitions_dynamic._test_gitlab_hook_logs_202201", database: "ci")
end
shared_examples 'truncating legacy tables on a database' do
@@ -64,19 +64,19 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
id bigserial not null,
created_at timestamptz not null,
item_id BIGINT NOT NULL,
- primary key (id, created_at),
+ PRIMARY KEY (id, created_at),
CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
) PARTITION BY RANGE(created_at);
- CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101
+ CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202201
PARTITION OF _test_gitlab_hook_logs
FOR VALUES FROM ('20220101') TO ('20220131');
- CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_20220201
+ CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202202
PARTITION OF _test_gitlab_hook_logs
FOR VALUES FROM ('20220201') TO ('20220228');
- ALTER TABLE _test_gitlab_hook_logs DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101;
+ ALTER TABLE _test_gitlab_hook_logs DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_hook_logs_202201;
SQL
main_connection.execute(main_tables_sql)
@@ -124,14 +124,14 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
Gitlab::Database::SharedModel.using_connection(main_connection) do
Postgresql::DetachedPartition.create!(
- table_name: '_test_gitlab_hook_logs_20220101',
+ table_name: '_test_gitlab_hook_logs_202201',
drop_after: Time.current
)
end
Gitlab::Database::SharedModel.using_connection(ci_connection) do
Postgresql::DetachedPartition.create!(
- table_name: '_test_gitlab_hook_logs_20220101',
+ table_name: '_test_gitlab_hook_logs_202201',
drop_after: Time.current
)
end
@@ -237,6 +237,25 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
end
end
+ context 'when one of the attached partitions happened to be locked for writes' do
+ before do
+ skip if connection.pool.db_config.name != 'ci'
+
+ Gitlab::Database::LockWritesManager.new(
+ table_name: "#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_gitlab_hook_logs_202202",
+ connection: connection,
+ database_name: connection.pool.db_config.name,
+ with_retries: false
+ ).lock_writes
+ end
+
+ it 'truncates the locked partition successfully' do
+ expect do
+ truncate_legacy_tables
+ end.to change { ci_db_partitioned_item.count }.from(5).to(0)
+ end
+ end
+
context 'with geo configured' do
let(:geo_connection) { Gitlab::Database.database_base_models[:geo].connection }
diff --git a/spec/views/layouts/snippets.html.haml_spec.rb b/spec/views/layouts/snippets.html.haml_spec.rb
index 581b7a898fa..69378906bcd 100644
--- a/spec/views/layouts/snippets.html.haml_spec.rb
+++ b/spec/views/layouts/snippets.html.haml_spec.rb
@@ -3,19 +3,45 @@
require 'spec_helper'
RSpec.describe 'layouts/snippets', feature_category: :snippets do
- let(:user) { build_stubbed(:user) }
-
before do
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
end
- describe "sidebar" do
- context "when @snippet is not set" do
+ describe 'sidebar' do
+ context 'when feature flag is on' do
+ context 'when signed in' do
+ let(:user) { build_stubbed(:user) }
+
+ it 'renders the "Your work" sidebar' do
+ render
+
+ expect(rendered).to have_css('aside.nav-sidebar[aria-label="Your work"]')
+ end
+ end
+
+ context 'when not signed in' do
+ let(:user) { nil }
+
+ it 'renders no sidebar' do
+ render
+
+ expect(rendered).not_to have_css('aside.nav-sidebar')
+ end
+ end
+ end
+
+ context 'when feature flag is off' do
+ before do
+ stub_feature_flags(your_work_sidebar: false)
+ end
+
+ let(:user) { build_stubbed(:user) }
+
it 'renders no sidebar' do
render
- expect(rendered).not_to have_css("aside.nav-sidebar")
+ expect(rendered).not_to have_css('aside.nav-sidebar')
end
end
end