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-14 15:09:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-14 15:09:34 +0300
commit9a5dcad39c5dd81384ae4ec2398435883b944363 (patch)
tree3c684d30e4500028299d7948171e885b844a1ade /spec
parent0923a94d58cdd15cdb6379330e5eb41d30ccb8cc (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/projects.rb6
-rw-r--r--spec/factories/services.rb6
-rw-r--r--spec/features/groups/board_sidebar_spec.rb2
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb28
-rw-r--r--spec/features/projects/services/user_activates_issue_tracker_spec.rb15
-rw-r--r--spec/frontend/boards/mock_data.js144
-rw-r--r--spec/frontend/boards/stores/actions_spec.js17
-rw-r--r--spec/frontend/boards/stores/getters_spec.js15
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js55
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js4
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap8
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js10
-rw-r--r--spec/frontend/ide/commit_icon_spec.js1
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js2
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js43
-rw-r--r--spec/frontend/ide/helpers.js1
-rw-r--r--spec/frontend/ide/lib/files_spec.js15
-rw-r--r--spec/frontend/ide/services/index_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js24
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js2
-rw-r--r--spec/frontend/ide/stores/actions_spec.js15
-rw-r--r--spec/frontend/ide/stores/getters_spec.js11
-rw-r--r--spec/frontend/ide/stores/integration_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js18
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap4
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js8
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js4
-rw-r--r--spec/frontend/milestones/project_milestone_combobox_spec.js4
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap4
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js4
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js8
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js12
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js9
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js2
-rw-r--r--spec/frontend/sidebar/issuable_assignees_spec.js59
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap832
-rw-r--r--spec/helpers/notifications_helper_spec.rb12
-rw-r--r--spec/lib/backup/artifacts_spec.rb37
-rw-r--r--spec/lib/backup/files_spec.rb46
-rw-r--r--spec/lib/backup/pages_spec.rb30
-rw-r--r--spec/lib/backup/uploads_spec.rb18
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb43
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb111
-rw-r--r--spec/models/alert_management/alert_spec.rb27
-rw-r--r--spec/models/project_services/ewm_service_spec.rb61
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/presenters/alert_management/alert_presenter_spec.rb27
-rw-r--r--spec/presenters/alert_management/prometheus_alert_presenter_spec.rb6
-rw-r--r--spec/presenters/projects/prometheus/alert_presenter_spec.rb120
-rw-r--r--spec/requests/api/variables_spec.rb64
-rw-r--r--spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb28
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb13
-rw-r--r--spec/views/projects/merge_requests/edit.html.haml_spec.rb1
59 files changed, 1162 insertions, 900 deletions
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 99caf24cbf1..e3411e4f925 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -392,6 +392,12 @@ FactoryBot.define do
end
end
+ factory :ewm_project, parent: :project do
+ has_external_issue_tracker { true }
+
+ ewm_service
+ end
+
factory :project_with_design, parent: :project do
after(:create) do |project|
issue = create(:issue, project: project)
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 7fbf6f16dc7..9056fd97f13 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -116,6 +116,12 @@ FactoryBot.define do
issue_tracker
end
+ factory :ewm_service do
+ project
+ active { true }
+ issue_tracker
+ end
+
trait :issue_tracker do
transient do
create_data { true }
diff --git a/spec/features/groups/board_sidebar_spec.rb b/spec/features/groups/board_sidebar_spec.rb
index 690d661ba2f..3bbeed10948 100644
--- a/spec/features/groups/board_sidebar_spec.rb
+++ b/spec/features/groups/board_sidebar_spec.rb
@@ -19,8 +19,6 @@ RSpec.describe 'Group Issue Boards', :js do
let(:card) { find('.board:nth-child(1)').first('.board-card') }
before do
- # stubbing until sidebar work is done: https://gitlab.com/gitlab-org/gitlab/-/issues/230711
- stub_feature_flags(graphql_board_lists: false)
sign_in(user)
visit group_board_path(group, board)
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index cc631cc6dd0..7321f2243b9 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -152,9 +152,7 @@ RSpec.describe "Issues > User edits issue", :js do
visit project_issue_path(project, issue2)
page.within '.assignee' do
- page.within '.value .author' do
- expect(page).to have_content user.name
- end
+ expect(page).to have_content user.name
click_link 'Edit'
click_link user.name
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index 2c949ed84f4..397ca70f4a1 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -20,4 +20,32 @@ RSpec.describe 'Merge request > User edits MR' do
include_context 'merge request edit context'
it_behaves_like 'an editable merge request'
end
+
+ context 'when merge_request_reviewers is turned on' do
+ before do
+ stub_feature_flags(merge_request_reviewers: true)
+ end
+
+ context 'non-fork merge request' do
+ include_context 'merge request edit context'
+ it_behaves_like 'an editable merge request with reviewers'
+ end
+
+ context 'for a forked project' do
+ let(:source_project) { fork_project(target_project, nil, repository: true) }
+
+ include_context 'merge request edit context'
+ it_behaves_like 'an editable merge request with reviewers'
+ end
+ end
+
+ context 'when merge_request_reviewers is turned off' do
+ before do
+ stub_feature_flags(merge_request_reviewers: false)
+ end
+
+ it 'does not render reviewers dropdown' do
+ expect(page).not_to have_selector('.js-reviewer-search')
+ end
+ end
end
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
index c7389460a07..d7ae79a1543 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'User activates issue tracker', :js do
fill_in 'service_new_issue_url', with: url unless skip_new_issue_url
end
- shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false|
+ shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false, skip_test: false|
describe 'user sets and activates the Service' do
context 'when the connection test succeeds' do
before do
@@ -25,7 +25,11 @@ RSpec.describe 'User activates issue tracker', :js do
visit_project_integration(tracker)
fill_form(skip_new_issue_url: skip_new_issue_url)
- click_test_integration
+ if skip_test
+ click_button('Save changes')
+ else
+ click_test_integration
+ end
end
it 'activates the service' do
@@ -47,7 +51,11 @@ RSpec.describe 'User activates issue tracker', :js do
visit_project_integration(tracker)
fill_form(skip_new_issue_url: skip_new_issue_url)
- click_test_then_save_integration
+ if skip_test
+ click_button('Save changes')
+ else
+ click_test_then_save_integration
+ end
expect(page).to have_content("#{tracker} activated.")
expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_')))
@@ -80,4 +88,5 @@ RSpec.describe 'User activates issue tracker', :js do
it_behaves_like 'external issue tracker activation', tracker: 'YouTrack', skip_new_issue_url: true
it_behaves_like 'external issue tracker activation', tracker: 'Bugzilla'
it_behaves_like 'external issue tracker activation', tracker: 'Custom Issue Tracker'
+ it_behaves_like 'external issue tracker activation', tracker: 'EWM', skip_test: true
end
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index a84970eb736..717ab5f3add 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -98,35 +98,12 @@ export const mockMilestone = {
due_date: '2019-12-31',
};
-const assignees = [
- {
- id: 'gid://gitlab/User/2',
- username: 'angelina.herman',
- name: 'Bernardina Bosco',
- avatar: 'https://www.gravatar.com/avatar/eb7b664b13a30ad9f9ba4b61d7075470?s=80&d=identicon',
- webUrl: 'http://127.0.0.1:3000/angelina.herman',
- },
-];
-
-const labels = [
- {
- id: 'gid://gitlab/GroupLabel/5',
- title: 'Cosync',
- color: '#34ebec',
- description: null,
- },
-];
-
export const rawIssue = {
- title: 'Issue 1',
- id: 'gid://gitlab/Issue/436',
- iid: 27,
- dueDate: null,
- timeEstimate: 0,
- weight: null,
+ title: 'Testing',
+ id: 'gid://gitlab/Issue/1',
+ iid: 1,
confidential: false,
- referencePath: 'gitlab-org/gitlab-test#27',
- path: '/gitlab-org/gitlab-test/-/issues/27',
+ referencePath: 'gitlab-org/gitlab-test#1',
labels: {
nodes: [
{
@@ -138,24 +115,23 @@ export const rawIssue = {
],
},
assignees: {
- nodes: assignees,
- },
- epic: {
- id: 'gid://gitlab/Epic/41',
+ nodes: [
+ {
+ id: 1,
+ name: 'name',
+ username: 'username',
+ avatar_url: 'http://avatar_url',
+ },
+ ],
},
};
export const mockIssue = {
- id: 'gid://gitlab/Issue/436',
- iid: 27,
- title: 'Issue 1',
- dueDate: null,
- timeEstimate: 0,
- weight: null,
+ title: 'Testing',
+ id: 1,
+ iid: 1,
confidential: false,
- referencePath: 'gitlab-org/gitlab-test#27',
- path: '/gitlab-org/gitlab-test/-/issues/27',
- assignees,
+ referencePath: 'gitlab-org/gitlab-test#1',
labels: [
{
id: 1,
@@ -164,64 +140,44 @@ export const mockIssue = {
description: 'testing',
},
],
- epic: {
- id: 'gid://gitlab/Epic/41',
- },
+ assignees: [
+ {
+ id: 1,
+ name: 'name',
+ username: 'username',
+ avatar_url: 'http://avatar_url',
+ },
+ ],
};
export const mockIssueWithModel = new ListIssue(mockIssue);
export const mockIssue2 = {
- id: 'gid://gitlab/Issue/437',
- iid: 28,
- title: 'Issue 2',
- dueDate: null,
- timeEstimate: 0,
- weight: null,
+ title: 'Planning',
+ id: 2,
+ iid: 2,
confidential: false,
referencePath: 'gitlab-org/gitlab-test#2',
- path: '/gitlab-org/gitlab-test/-/issues/28',
- assignees,
- labels,
- epic: {
- id: 'gid://gitlab/Epic/40',
- },
+ labels: [
+ {
+ id: 1,
+ title: 'plan',
+ color: 'blue',
+ description: 'planning',
+ },
+ ],
+ assignees: [
+ {
+ id: 1,
+ name: 'name',
+ username: 'username',
+ avatar_url: 'http://avatar_url',
+ },
+ ],
};
export const mockIssue2WithModel = new ListIssue(mockIssue2);
-export const mockIssue3 = {
- id: 'gid://gitlab/Issue/438',
- iid: 29,
- title: 'Issue 3',
- referencePath: '#29',
- dueDate: null,
- timeEstimate: 0,
- weight: null,
- confidential: false,
- path: '/gitlab-org/gitlab-test/-/issues/28',
- assignees,
- labels,
- epic: null,
-};
-
-export const mockIssue4 = {
- id: 'gid://gitlab/Issue/439',
- iid: 30,
- title: 'Issue 4',
- referencePath: '#30',
- dueDate: null,
- timeEstimate: 0,
- weight: null,
- confidential: false,
- path: '/gitlab-org/gitlab-test/-/issues/28',
- assignees,
- labels,
- epic: null,
-};
-
-export const mockIssues = [mockIssue, mockIssue2];
-
export const BoardsMockData = {
GET: {
'/test/-/boards/1/lists/300/issues?id=300&page=1': {
@@ -283,7 +239,6 @@ export const mockLists = [
label: null,
assignee: null,
milestone: null,
- loading: false,
},
{
id: 'gid://gitlab/List/2',
@@ -300,22 +255,9 @@ export const mockLists = [
},
assignee: null,
milestone: null,
- loading: false,
},
];
export const mockListsWithModel = mockLists.map(listMock =>
Vue.observable(new List({ ...listMock, doNotFetchIssues: true })),
);
-
-export const mockIssuesByListId = {
- 'gid://gitlab/List/1': [mockIssue.id, mockIssue3.id, mockIssue4.id],
- 'gid://gitlab/List/2': mockIssues.map(({ id }) => id),
-};
-
-export const issues = {
- [mockIssue.id]: mockIssue,
- [mockIssue2.id]: mockIssue2,
- [mockIssue3.id]: mockIssue3,
- [mockIssue4.id]: mockIssue4,
-};
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 8efad4d3ac7..4eb1a370a9f 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -3,6 +3,7 @@ import {
mockListsWithModel,
mockLists,
mockIssue,
+ mockIssue2,
mockIssueWithModel,
mockIssue2WithModel,
rawIssue,
@@ -133,7 +134,7 @@ describe('createList', () => {
{ backlog: true },
state,
[],
- [{ type: 'addList', payload: backlogList }],
+ [{ type: 'addList', payload: { ...backlogList, id: 1 } }],
done,
);
});
@@ -231,15 +232,19 @@ describe('deleteList', () => {
expectNotImplemented(actions.deleteList);
});
+describe('fetchIssuesForList', () => {
+ expectNotImplemented(actions.fetchIssuesForList);
+});
+
describe('moveIssue', () => {
const listIssues = {
- 'gid://gitlab/List/1': [436, 437],
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
'gid://gitlab/List/2': [],
};
const issues = {
- '436': mockIssueWithModel,
- '437': mockIssue2WithModel,
+ '1': mockIssueWithModel,
+ '2': mockIssue2WithModel,
};
const state = {
@@ -264,7 +269,7 @@ describe('moveIssue', () => {
testAction(
actions.moveIssue,
{
- issueId: '436',
+ issueId: mockIssue.id,
issueIid: mockIssue.iid,
issuePath: mockIssue.referencePath,
fromListId: 'gid://gitlab/List/1',
@@ -303,7 +308,7 @@ describe('moveIssue', () => {
testAction(
actions.moveIssue,
{
- issueId: '436',
+ issueId: mockIssue.id,
issueIid: mockIssue.iid,
issuePath: mockIssue.referencePath,
fromListId: 'gid://gitlab/List/1',
diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js
index 288143a0f21..267451845ba 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -1,6 +1,5 @@
import getters from '~/boards/stores/getters';
import { inactiveId } from '~/boards/constants';
-import { mockIssue, mockIssue2, mockIssues, mockIssuesByListId, issues } from '../mock_data';
describe('Boards - Getters', () => {
describe('getLabelToggleState', () => {
@@ -116,18 +115,4 @@ describe('Boards - Getters', () => {
expect(getters.getActiveIssue(state)).toEqual(expected);
});
});
-
- describe('getIssues', () => {
- const boardsState = {
- issuesByListId: mockIssuesByListId,
- issues,
- };
- it('returns issues for a given listId', () => {
- const getIssueById = issueId => [mockIssue, mockIssue2].find(({ id }) => id === issueId);
-
- expect(getters.getIssues(boardsState, { getIssueById })('gid://gitlab/List/2')).toEqual(
- mockIssues,
- );
- });
- });
});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index a13a99a507e..350eccfa82e 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -54,11 +54,11 @@ describe('Board Store Mutations', () => {
});
});
- describe('RECEIVE_BOARD_LISTS_SUCCESS', () => {
+ describe('RECEIVE_LISTS', () => {
it('Should set boardLists to state', () => {
const lists = [listObj, listObjDuplicate];
- mutations[types.RECEIVE_BOARD_LISTS_SUCCESS](state, lists);
+ mutations[types.RECEIVE_LISTS](state, lists);
expect(state.boardLists).toEqual(lists);
});
@@ -145,33 +145,6 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR);
});
- describe('RECEIVE_ISSUES_FOR_LIST_SUCCESS', () => {
- it('updates issuesByListId and issues on state', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id],
- };
- const issues = {
- '1': mockIssue,
- };
-
- state = {
- ...state,
- isLoadingIssues: true,
- issuesByListId: {},
- issues: {},
- boardLists: mockListsWithModel,
- };
-
- mutations.RECEIVE_ISSUES_FOR_LIST_SUCCESS(state, {
- listIssues: { listData: listIssues, issues },
- listId: 'gid://gitlab/List/1',
- });
-
- expect(state.issuesByListId).toEqual(listIssues);
- expect(state.issues).toEqual(issues);
- });
- });
-
describe('REQUEST_ISSUES_FOR_ALL_LISTS', () => {
it('sets isLoadingIssues to true', () => {
expect(state.isLoadingIssues).toBe(false);
@@ -182,28 +155,10 @@ describe('Board Store Mutations', () => {
});
});
- describe('RECEIVE_ISSUES_FOR_LIST_FAILURE', () => {
- it('sets error message', () => {
- state = {
- ...state,
- boardLists: mockListsWithModel,
- error: undefined,
- };
-
- const listId = 'gid://gitlab/List/1';
-
- mutations.RECEIVE_ISSUES_FOR_LIST_FAILURE(state, listId);
-
- expect(state.error).toEqual(
- 'An error occurred while fetching the board issues. Please reload the page.',
- );
- });
- });
-
describe('RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS', () => {
it('sets isLoadingIssues to false and updates issuesByListId object', () => {
const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id],
+ '': [mockIssue.id],
};
const issues = {
'1': mockIssue,
@@ -332,7 +287,7 @@ describe('Board Store Mutations', () => {
describe('MOVE_ISSUE_SUCCESS', () => {
it('updates issue in issues state', () => {
const issues = {
- '436': { id: rawIssue.id },
+ '1': { id: rawIssue.id },
};
state = {
@@ -344,7 +299,7 @@ describe('Board Store Mutations', () => {
issue: rawIssue,
});
- expect(state.issues).toEqual({ '436': { ...mockIssueWithModel, id: 436 } });
+ expect(state.issues).toEqual({ '1': { ...mockIssueWithModel, id: 1 } });
});
});
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 644cd0b5f27..99cb864ce34 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdownItem, GlNewDropdown } from '@gitlab/ui';
+import { GlDeprecatedDropdownItem, GlDropdown } from '@gitlab/ui';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
@@ -92,7 +92,7 @@ describe('Deploy freeze timezone dropdown', () => {
});
it('renders selected time zone as dropdown label', () => {
- expect(wrapper.find(GlNewDropdown).vm.text).toBe('Alaska');
+ expect(wrapper.find(GlDropdown).vm.text).toBe('Alaska');
});
});
});
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
index d6fd09eb698..335cbe9c55e 100644
--- a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
+++ b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management design version dropdown component renders design version dropdown button 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="tertiary"
headertext=""
issueiid=""
@@ -35,11 +35,11 @@ exports[`Design management design version dropdown component renders design vers
1
</gl-new-dropdown-item-stub>
-</gl-new-dropdown-stub>
+</gl-dropdown-stub>
`;
exports[`Design management design version dropdown component renders design version list 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="tertiary"
headertext=""
issueiid=""
@@ -73,5 +73,5 @@ exports[`Design management design version dropdown component renders design vers
1
</gl-new-dropdown-item-stub>
-</gl-new-dropdown-stub>
+</gl-dropdown-stub>
`;
diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
index f4206cdaeb3..cc4274b0d02 100644
--- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
+++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlNewDropdownItem, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlNewDropdownItem, GlSprintf } from '@gitlab/ui';
import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue';
import mockAllVersions from './mock_data/all_versions';
@@ -75,7 +75,7 @@ describe('Design management design version dropdown component', () => {
createComponent();
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
@@ -83,7 +83,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ maxVersions: 1 });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
@@ -91,7 +91,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe(`Showing version #1`);
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
});
});
@@ -99,7 +99,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
diff --git a/spec/frontend/ide/commit_icon_spec.js b/spec/frontend/ide/commit_icon_spec.js
index e4a7394b089..0dfcae00298 100644
--- a/spec/frontend/ide/commit_icon_spec.js
+++ b/spec/frontend/ide/commit_icon_spec.js
@@ -7,7 +7,6 @@ const createFile = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index 5a591d3dcd0..d5080acfe9f 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -34,7 +34,7 @@ describe('RepoTab', () => {
});
vm.$store.state.openFiles.push(vm.tab);
const close = vm.$el.querySelector('.multi-file-tab-close');
- const name = vm.$el.querySelector(`[title="${vm.tab.url}"]`);
+ const name = vm.$el.querySelector(`[title]`);
expect(close.innerHTML).toContain('#close');
expect(name.textContent.trim()).toEqual(vm.tab.name);
diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js
index df5b01770f5..b251f207853 100644
--- a/spec/frontend/ide/components/repo_tabs_spec.js
+++ b/spec/frontend/ide/components/repo_tabs_spec.js
@@ -1,27 +1,40 @@
-import Vue from 'vue';
-import repoTabs from '~/ide/components/repo_tabs.vue';
-import createComponent from '../../helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { createStore } from '~/ide/stores';
+import RepoTabs from '~/ide/components/repo_tabs.vue';
import { file } from '../helpers';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('RepoTabs', () => {
- const openedFiles = [file('open1'), file('open2')];
- const RepoTabs = Vue.extend(repoTabs);
- let vm;
+ let wrapper;
+ let store;
+
+ beforeEach(() => {
+ store = createStore();
+ store.state.openFiles = [file('open1'), file('open2')];
+
+ wrapper = mount(RepoTabs, {
+ propsData: {
+ files: store.state.openFiles,
+ viewer: 'editor',
+ activeFile: file('activeFile'),
+ },
+ store,
+ localVue,
+ });
+ });
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders a list of tabs', done => {
- vm = createComponent(RepoTabs, {
- files: openedFiles,
- viewer: 'editor',
- activeFile: file('activeFile'),
- });
- openedFiles[0].active = true;
+ store.state.openFiles[0].active = true;
- vm.$nextTick(() => {
- const tabs = [...vm.$el.querySelectorAll('.multi-file-tab')];
+ wrapper.vm.$nextTick(() => {
+ const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
expect(tabs.length).toEqual(2);
expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index 8caa9c2b437..0e85b523cbd 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -6,7 +6,6 @@ export const file = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js
index 6974cdc4074..b223cf64278 100644
--- a/spec/frontend/ide/lib/files_spec.js
+++ b/spec/frontend/ide/lib/files_spec.js
@@ -2,25 +2,16 @@ import { viewerInformationForPath } from '~/vue_shared/components/content_viewer
import { decorateFiles, splitParent } from '~/ide/lib/files';
import { decorateData } from '~/ide/stores/utils';
-const TEST_BRANCH_ID = 'lorem-ipsum';
-const TEST_PROJECT_ID = 10;
-
const createEntries = paths => {
const createEntry = (acc, { path, type, children }) => {
- // Sometimes we need to end the url with a '/'
- const createUrl = base => (type === 'tree' ? `${base}/` : base);
-
const { name, parent } = splitParent(path);
const previewMode = viewerInformationForPath(name);
acc[path] = {
...decorateData({
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH_ID,
id: path,
name,
path,
- url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${path}`),
type,
previewMode,
binary: (previewMode && previewMode.binary) || false,
@@ -56,11 +47,7 @@ describe('IDE lib decorate files', () => {
{ path: 'README.md', type: 'blob', children: [] },
]);
- const { entries, treeList } = decorateFiles({
- data,
- branchId: TEST_BRANCH_ID,
- projectId: TEST_PROJECT_ID,
- });
+ const { entries, treeList } = decorateFiles({ data });
// Here we test the keys and then each key/value individually because `expect(entries).toEqual(expectedEntries)`
// was taking a very long time for some reason. Probably due to large objects and nested `expect.objectContaining`.
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index bc3f86702cf..d2c32a81811 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -146,7 +146,7 @@ describe('IDE services', () => {
it('gives back file.baseRaw for files with that property present', () => {
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -155,7 +155,7 @@ describe('IDE services', () => {
file.tempFile = true;
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -192,7 +192,7 @@ describe('IDE services', () => {
});
it('fetches file content', () =>
- services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
}));
},
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 88e7a9fff36..5166e07abcb 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -27,6 +27,10 @@ describe('IDE store file actions', () => {
};
store = createStore();
+
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
router = createRouter(store);
jest.spyOn(store, 'commit');
@@ -72,10 +76,7 @@ describe('IDE store file actions', () => {
});
it('closes file & opens next available file', () => {
- const f = {
- ...file('newOpenFile'),
- url: '/newOpenFile',
- };
+ const f = file('newOpenFile');
store.state.openFiles.push(f);
store.state.entries[f.path] = f;
@@ -84,7 +85,7 @@ describe('IDE store file actions', () => {
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
- expect(router.push).toHaveBeenCalledWith(`/project${f.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/newOpenFile/');
});
});
@@ -296,7 +297,6 @@ describe('IDE store file actions', () => {
describe('Re-named success', () => {
beforeEach(() => {
localFile = file(`newCreate-${Math.random()}`);
- localFile.url = `project/getFileDataURL`;
localFile.prevPath = 'old-dull-file';
localFile.path = 'new-shiny-file';
store.state.entries[localFile.path] = localFile;
@@ -393,7 +393,11 @@ describe('IDE store file actions', () => {
tmpFile.mrChange = { new_file: false };
return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
- expect(service.getBaseRawFileData).toHaveBeenCalledWith(tmpFile, 'SHA');
+ expect(service.getBaseRawFileData).toHaveBeenCalledWith(
+ tmpFile,
+ 'gitlab-org/gitlab-ce',
+ 'SHA',
+ );
expect(tmpFile.baseRaw).toBe('baseraw');
});
});
@@ -660,7 +664,7 @@ describe('IDE store file actions', () => {
});
it('pushes route for active file', () => {
- expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/tempFile/');
});
});
});
@@ -735,10 +739,8 @@ describe('IDE store file actions', () => {
});
it('pushes router URL when added', () => {
- store.state.currentBranchId = 'master';
-
return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/');
});
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index 62971b9cad6..b1cceda9d85 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -453,11 +453,9 @@ describe('IDE store merge request actions', () => {
it('updates activity bar view and gets file data, if changes are found', done => {
store.state.entries.foo = {
- url: 'test',
type: 'blob',
};
store.state.entries.bar = {
- url: 'test',
type: 'blob',
};
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index f77dbd80025..ebf39df2f6f 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -123,7 +123,6 @@ describe('Multi-file store actions', () => {
it('creates temp tree', done => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'test',
type: 'tree',
})
@@ -150,7 +149,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing/test',
type: 'tree',
})
@@ -176,7 +174,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing',
type: 'tree',
})
@@ -197,7 +194,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -217,7 +213,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -237,7 +232,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -249,7 +243,7 @@ describe('Multi-file store actions', () => {
});
it('sets tmp file as active', () => {
- createTempEntry(store, { name: 'test', branchId: 'mybranch', type: 'blob' });
+ createTempEntry(store, { name: 'test', type: 'blob' });
expect(store.dispatch).toHaveBeenCalledWith('setFileActive', 'test');
});
@@ -262,7 +256,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name: 'test',
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -780,9 +773,11 @@ describe('Multi-file store actions', () => {
});
it('routes to the renamed file if the original file has been opened', done => {
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
Object.assign(store.state.entries.orig, {
opened: true,
- url: '/foo-bar.md',
});
store
@@ -792,7 +787,7 @@ describe('Multi-file store actions', () => {
})
.then(() => {
expect(router.push.mock.calls).toHaveLength(1);
- expect(router.push).toHaveBeenCalledWith(`/project/foo-bar.md`);
+ expect(router.push).toHaveBeenCalledWith(`/project/test/test/tree/master/-/renamed/`);
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index dcf05329ce0..17fc08144f6 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -482,4 +482,15 @@ describe('IDE store getters', () => {
expect(localStore.getters.getAvailableFileName('foo-bar1.jpg')).toBe('foo-bar1.jpg');
});
});
+
+ describe('getUrlForPath', () => {
+ it('returns a route url for the given path', () => {
+ localState.currentProjectId = 'test/test';
+ localState.currentBranchId = 'master';
+
+ expect(localStore.getters.getUrlForPath('path/to/foo/bar-1.jpg')).toBe(
+ `/project/test/test/tree/master/-/path/to/foo/bar-1.jpg/`,
+ );
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/integration_spec.js b/spec/frontend/ide/stores/integration_spec.js
index f95f036f572..b6a7c7fd02d 100644
--- a/spec/frontend/ide/stores/integration_spec.js
+++ b/spec/frontend/ide/stores/integration_spec.js
@@ -36,8 +36,6 @@ describe('IDE store integration', () => {
beforeEach(() => {
const { entries, treeList } = decorateFiles({
data: [`${TEST_PATH_DIR}/`, TEST_PATH, 'README.md'],
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH,
});
Object.assign(entries[TEST_PATH], {
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 1b29648fb8b..09e9481e5d4 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -113,8 +113,6 @@ describe('Multi-file store mutations', () => {
},
treeList: [tmpFile],
},
- projectId: 'gitlab-ce',
- branchId: 'master',
});
expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
@@ -272,7 +270,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
}),
);
@@ -337,7 +334,6 @@ describe('Multi-file store mutations', () => {
};
Object.assign(localState.entries['root-folder/oldPath'], {
parentPath: 'root-folder',
- url: 'root-folder/oldPath-blob-root-folder/oldPath',
});
mutations.RENAME_ENTRY(localState, {
@@ -366,9 +362,6 @@ describe('Multi-file store mutations', () => {
});
it('renames entry, preserving old parameters', () => {
- Object.assign(localState.entries.oldPath, {
- url: `project/-/oldPath`,
- });
const oldPathData = localState.entries.oldPath;
mutations.RENAME_ENTRY(localState, {
@@ -382,12 +375,10 @@ describe('Multi-file store mutations', () => {
id: 'newPath',
path: 'newPath',
name: 'newPath',
- url: `project/-/newPath`,
key: expect.stringMatching('newPath'),
prevId: 'oldPath',
prevName: 'oldPath',
prevPath: 'oldPath',
- prevUrl: `project/-/oldPath`,
prevKey: oldPathData.key,
prevParentPath: oldPathData.parentPath,
});
@@ -409,7 +400,6 @@ describe('Multi-file store mutations', () => {
prevId: expect.anything(),
prevName: expect.anything(),
prevPath: expect.anything(),
- prevUrl: expect.anything(),
prevKey: expect.anything(),
prevParentPath: expect.anything(),
}),
@@ -419,7 +409,7 @@ describe('Multi-file store mutations', () => {
it('properly handles files with spaces in name', () => {
const path = 'my fancy path';
const newPath = 'new path';
- const oldEntry = { ...file(path, path, 'blob'), url: `project/-/${path}` };
+ const oldEntry = file(path, path, 'blob');
localState.entries[path] = oldEntry;
@@ -435,12 +425,10 @@ describe('Multi-file store mutations', () => {
id: newPath,
path: newPath,
name: newPath,
- url: `project/-/new path`,
key: expect.stringMatching(newPath),
prevId: path,
prevName: path,
prevPath: path,
- prevUrl: `project/-/my fancy path`,
prevKey: oldEntry.key,
prevParentPath: oldEntry.parentPath,
});
@@ -549,7 +537,7 @@ describe('Multi-file store mutations', () => {
it('correctly saves original values if an entry is renamed multiple times', () => {
const original = { ...localState.entries.oldPath };
- const paramsToCheck = ['prevId', 'prevPath', 'prevName', 'prevUrl'];
+ const paramsToCheck = ['prevId', 'prevPath', 'prevName'];
const expectedObj = paramsToCheck.reduce(
(o, param) => ({ ...o, [param]: original[param.replace('prev', '').toLowerCase()] }),
{},
@@ -577,7 +565,6 @@ describe('Multi-file store mutations', () => {
prevId: 'lorem/orig',
prevPath: 'lorem/orig',
prevName: 'orig',
- prevUrl: 'project/-/loren/orig',
prevKey: 'lorem/orig',
prevParentPath: 'lorem',
};
@@ -602,7 +589,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
}),
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
index fd6af59eb48..a3a7d96bf14 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -45,7 +45,7 @@ exports[`Alert integration settings form default state should match the default
</gl-link-stub>
</label>
- <gl-new-dropdown-stub
+ <gl-dropdown-stub
block="true"
category="tertiary"
data-qa-selector="incident_templates_dropdown"
@@ -68,7 +68,7 @@ exports[`Alert integration settings form default state should match the default
No template selected
</gl-new-dropdown-item-stub>
- </gl-new-dropdown-stub>
+ </gl-dropdown-stub>
</gl-form-group-stub>
<gl-form-group-stub
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
index 00ec8fc36cd..44e14cb3760 100644
--- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlLink } from '@gitlab/ui';
+import { GlDropdown, GlLink } from '@gitlab/ui';
import { createStore } from '~/integrations/edit/store';
import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
@@ -34,14 +34,14 @@ describe('OverrideDropdown', () => {
});
const findGlLink = () => wrapper.find(GlLink);
- const findGlNewDropdown = () => wrapper.find(GlNewDropdown);
+ const findGlDropdown = () => wrapper.find(GlDropdown);
describe('template', () => {
describe('override prop is true', () => {
it('renders GlToggle as disabled', () => {
createComponent();
- expect(findGlNewDropdown().props('text')).toBe('Use custom settings');
+ expect(findGlDropdown().props('text')).toBe('Use custom settings');
});
});
@@ -49,7 +49,7 @@ describe('OverrideDropdown', () => {
it('renders GlToggle as disabled', () => {
createComponent({ override: false });
- expect(findGlNewDropdown().props('text')).toBe('Use default settings');
+ expect(findGlDropdown().props('text')).toBe('Use default settings');
});
});
diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js
index 39cb63af2f0..d184c054b8a 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlButton, GlNewDropdown, GlFormSelect, GlLabel, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlDropdown, GlFormSelect, GlLabel, GlTable } from '@gitlab/ui';
import { getByRole } from '@testing-library/dom';
import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
@@ -35,7 +35,7 @@ describe('JiraImportForm', () => {
const getTable = () => wrapper.find(GlTable);
- const getUserDropdown = () => getTable().find(GlNewDropdown);
+ const getUserDropdown = () => getTable().find(GlDropdown);
const getHeader = name => getByRole(wrapper.element, 'columnheader', { name });
diff --git a/spec/frontend/milestones/project_milestone_combobox_spec.js b/spec/frontend/milestones/project_milestone_combobox_spec.js
index 4859561c4e3..60d68aa5816 100644
--- a/spec/frontend/milestones/project_milestone_combobox_spec.js
+++ b/spec/frontend/milestones/project_milestone_combobox_spec.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { GlDropdown, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { ENTER_KEY } from '~/lib/utils/keys';
import MilestoneCombobox from '~/milestones/project_milestone_combobox.vue';
import { milestones as projectMilestones } from './mock_data';
@@ -53,7 +53,7 @@ describe('Milestone selector', () => {
});
it('renders the dropdown', () => {
- expect(wrapper.find(GlNewDropdown)).toExist();
+ expect(wrapper.find(GlDropdown)).toExist();
});
it('renders additional links', () => {
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index 80eacbe0a6a..a85c5a2bffc 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -32,7 +32,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<div
class="mb-2 pr-2 d-flex d-sm-block"
>
- <gl-new-dropdown-stub
+ <gl-dropdown-stub
category="tertiary"
class="flex-grow-1"
data-qa-selector="environments_dropdown"
@@ -69,7 +69,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
</div>
</div>
- </gl-new-dropdown-stub>
+ </gl-dropdown-stub>
</div>
<div
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index a9b8295f38e..56cc7a344fb 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
-import { GlNewDropdown, GlNewDropdownItem, GlButton } from '@gitlab/ui';
+import { GlDropdown, GlNewDropdownItem, GlButton } from '@gitlab/ui';
import { createStore } from '~/monitoring/stores';
import RefreshButton from '~/monitoring/components/refresh_button.vue';
@@ -15,7 +15,7 @@ describe('RefreshButton', () => {
};
const findRefreshBtn = () => wrapper.find(GlButton);
- const findDropdown = () => wrapper.find(GlNewDropdown);
+ const findDropdown = () => wrapper.find(GlDropdown);
const findOptions = () => findDropdown().findAll(GlNewDropdownItem);
const findOptionAt = index => findOptions().at(index);
diff --git a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
index 406a2f8872c..4867e3de09e 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,5 +1,5 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlNewDropdownItem, GlForm } from '@gitlab/ui';
+import { GlDropdown, GlNewDropdownItem, GlForm } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
@@ -23,7 +23,7 @@ describe('Pipeline New Form', () => {
};
const findForm = () => wrapper.find(GlForm);
- const findDropdown = () => wrapper.find(GlNewDropdown);
+ const findDropdown = () => wrapper.find(GlDropdown);
const findDropdownItems = () => wrapper.findAll(GlNewDropdownItem);
const findVariableRows = () => wrapper.findAll('[data-testid="ci-variable-row"]');
const findRemoveIcons = () => wrapper.findAll('[data-testid="remove-ci-variable-row"]');
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index d2afc1a1d55..8e65f0d4f71 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -17,7 +17,7 @@ describe('Linked pipeline', () => {
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]');
const findLinkedPipeline = () => wrapper.find({ ref: 'linkedPipeline' });
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findPipelineLink = () => wrapper.find('[data-testid="childPipelineLink"]');
+ const findPipelineLink = () => wrapper.find('[data-testid="pipelineLink"]');
const findExpandButton = () => wrapper.find('[data-testid="expandPipelineButton"]');
const createWrapper = (propsData, data = []) => {
@@ -126,14 +126,14 @@ describe('Linked pipeline', () => {
expect(findPipelineLabel().exists()).toBe(true);
});
- it('downsteram pipeline should link to the child pipeline if child', () => {
+ it('downstream pipeline should contain the correct link', () => {
createWrapper(downstreamProps);
expect(findPipelineLink().attributes('href')).toBe(mockData.triggered_by.path);
});
- it('upstream pipeline should not contain a link', () => {
+ it('upstream pipeline should contain the correct link', () => {
createWrapper(upstreamProps);
- expect(findPipelineLink().exists()).toBe(false);
+ expect(findPipelineLink().attributes('href')).toBe(mockData.triggered_by.path);
});
it.each`
diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
index 3a4aa94571e..2feb6aa5799 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -23,8 +23,6 @@ describe('Test reports suite table', () => {
const noCasesMessage = () => wrapper.find('.js-no-test-cases');
const allCaseRows = () => wrapper.findAll('.js-case-row');
const findCaseRowAtIndex = index => wrapper.findAll('.js-case-row').at(index);
- const allCaseNames = () =>
- wrapper.findAll('[data-testid="caseName"]').wrappers.map(el => el.attributes('text'));
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite) => {
@@ -63,16 +61,6 @@ describe('Test reports suite table', () => {
expect(allCaseRows().length).toBe(testCases.length);
});
- it('renders the failed tests first, skipped tests next, then successful tests', () => {
- const expectedCaseOrder = [
- ...testCases.filter(x => x.status === TestStatus.FAILED),
- ...testCases.filter(x => x.status === TestStatus.SKIPPED),
- ...testCases.filter(x => x.status === TestStatus.SUCCESS),
- ].map(x => x.name);
-
- expect(allCaseNames()).toEqual(expectedCaseOrder);
- });
-
it('renders the correct icon for each status', () => {
const failedTest = testCases.findIndex(x => x.status === TestStatus.FAILED);
const skippedTest = testCases.findIndex(x => x.status === TestStatus.SKIPPED);
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index a99c644a675..d38fdeb48a6 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -1,11 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import {
- GlNewDropdown,
- GlNewDropdownHeader,
- GlSearchBoxByType,
- GlNewDropdownItem,
-} from '@gitlab/ui';
+import { GlDropdown, GlNewDropdownHeader, GlSearchBoxByType, GlNewDropdownItem } from '@gitlab/ui';
import * as urlUtility from '~/lib/utils/url_utility';
import AuthorSelect from '~/projects/commits/components/author_select.vue';
import { createStore } from '~/projects/commits/store';
@@ -63,7 +58,7 @@ describe('Author Select', () => {
});
const findDropdownContainer = () => wrapper.find({ ref: 'dropdownContainer' });
- const findDropdown = () => wrapper.find(GlNewDropdown);
+ const findDropdown = () => wrapper.find(GlDropdown);
const findDropdownHeader = () => wrapper.find(GlNewDropdownHeader);
const findSearchBox = () => wrapper.find(GlSearchBoxByType);
const findDropdownItems = () => wrapper.findAll(GlNewDropdownItem);
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 6490bdcf038..77671287a4c 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -177,7 +177,7 @@ describe('Ref selector component', () => {
return waitForRequests();
});
- it('adds the provided ID to the GlNewDropdown instance', () => {
+ it('adds the provided ID to the GlDropdown instance', () => {
expect(wrapper.attributes().id).toBe(id);
});
});
diff --git a/spec/frontend/sidebar/issuable_assignees_spec.js b/spec/frontend/sidebar/issuable_assignees_spec.js
new file mode 100644
index 00000000000..aa930bd4198
--- /dev/null
+++ b/spec/frontend/sidebar/issuable_assignees_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue';
+
+describe('IssuableAssignees', () => {
+ let wrapper;
+
+ const createComponent = (props = { users: [] }) => {
+ wrapper = shallowMount(IssuableAssignees, {
+ provide: {
+ rootPath: '',
+ },
+ propsData: { ...props },
+ });
+ };
+ const findLabel = () => wrapper.find('[data-testid="assigneeLabel"');
+ const findUncollapsedAssigneeList = () => wrapper.find(UncollapsedAssigneeList);
+ const findEmptyAssignee = () => wrapper.find('[data-testid="none"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when no assignees are present', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders "None"', () => {
+ expect(findEmptyAssignee().text()).toBe('None');
+ });
+
+ it('renders "0 assignees"', () => {
+ expect(findLabel().text()).toBe('0 Assignees');
+ });
+ });
+
+ describe('when assignees are present', () => {
+ it('renders UncollapsedAssigneesList', () => {
+ createComponent({ users: [{ id: 1 }] });
+
+ expect(findUncollapsedAssigneeList().exists()).toBe(true);
+ });
+
+ it.each`
+ assignees | expected
+ ${[{ id: 1 }]} | ${'Assignee'}
+ ${[{ id: 1 }, { id: 2 }]} | ${'2 Assignees'}
+ `(
+ 'when assignees have a length of $assignees.length, it renders $expected',
+ ({ assignees, expected }) => {
+ createComponent({ users: assignees });
+
+ expect(findLabel().text()).toBe(expected);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
index e84eb7789d3..402a6daf922 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="primary"
headertext=""
right=""
@@ -94,5 +94,5 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
</div>
</div>
</div>
-</gl-new-dropdown-stub>
+</gl-dropdown-stub>
`;
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
index 2681488f76a..7b3c893ac05 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -3,7 +3,7 @@ import {
GlFilteredSearch,
GlButtonGroup,
GlButton,
- GlNewDropdown as GlDropdown,
+ GlDropdown,
GlNewDropdownItem as GlDropdownItem,
} from '@gitlab/ui';
diff --git a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
index 70a60a2f746..3990248d021 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
+++ b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
@@ -1,425 +1,433 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Resizable Skeleton Loader default setup renders the bars, labels, and grid with correct position, size, and rx percentages 1`] = `
-<svg
- class="gl-skeleton-loader"
- preserveAspectRatio="xMidYMid meet"
- version="1.1"
- viewBox="0 0 400 130"
+<div
+ class="gl-px-8"
>
- <rect
- clip-path="url(#null-idClip)"
- height="130"
- style="fill: url(#null-idGradient);"
- width="400"
- x="0"
- y="0"
- />
- <defs>
- <clippath
- id="null-idClip"
- >
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="30%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="60%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="90%"
- />
-
- <rect
- data-testid="skeleton-chart-bar"
- height="5%"
- rx="0.4%"
- width="6%"
- x="5.875%"
- y="85%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="7%"
- rx="0.4%"
- width="6%"
- x="17.625%"
- y="83%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="9%"
- rx="0.4%"
- width="6%"
- x="29.375%"
- y="81%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="14%"
- rx="0.4%"
- width="6%"
- x="41.125%"
- y="76%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="21%"
- rx="0.4%"
- width="6%"
- x="52.875%"
- y="69%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="35%"
- rx="0.4%"
- width="6%"
- x="64.625%"
- y="55%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="50%"
- rx="0.4%"
- width="6%"
- x="76.375%"
- y="40%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="80%"
- rx="0.4%"
- width="6%"
- x="88.125%"
- y="10%"
- />
-
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="6.875%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="18.625%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="30.375%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="42.125%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="53.875%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="65.625%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="77.375%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="89.125%"
- y="95%"
- />
- </clippath>
- <lineargradient
- id="null-idGradient"
- >
- <stop
- class="primary-stop"
- offset="0%"
+ <svg
+ class="gl-skeleton-loader"
+ preserveAspectRatio="xMidYMid meet"
+ version="1.1"
+ viewBox="0 0 400 130"
+ >
+ <rect
+ clip-path="url(#null-idClip)"
+ height="130"
+ style="fill: url(#null-idGradient);"
+ width="400"
+ x="0"
+ y="0"
+ />
+ <defs>
+ <clippath
+ id="null-idClip"
>
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-2; 1"
- />
- </stop>
- <stop
- class="secondary-stop"
- offset="50%"
- >
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-1.5; 1.5"
- />
- </stop>
- <stop
- class="primary-stop"
- offset="100%"
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="30%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="60%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="90%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="5%"
+ rx="0.4%"
+ width="4%"
+ x="6%"
+ y="85%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="7%"
+ rx="0.4%"
+ width="4%"
+ x="18%"
+ y="83%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="9%"
+ rx="0.4%"
+ width="4%"
+ x="30%"
+ y="81%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="14%"
+ rx="0.4%"
+ width="4%"
+ x="42%"
+ y="76%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="21%"
+ rx="0.4%"
+ width="4%"
+ x="54%"
+ y="69%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="35%"
+ rx="0.4%"
+ width="4%"
+ x="66%"
+ y="55%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="50%"
+ rx="0.4%"
+ width="4%"
+ x="78%"
+ y="40%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="80%"
+ rx="0.4%"
+ width="4%"
+ x="90%"
+ y="10%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="6.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="18.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="30.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="42.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="54.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="66.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="78.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="90.5%"
+ y="97%"
+ />
+ </clippath>
+ <lineargradient
+ id="null-idGradient"
>
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-1; 2"
- />
- </stop>
- </lineargradient>
- </defs>
-</svg>
+ <stop
+ class="primary-stop"
+ offset="0%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-2; 1"
+ />
+ </stop>
+ <stop
+ class="secondary-stop"
+ offset="50%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1.5; 1.5"
+ />
+ </stop>
+ <stop
+ class="primary-stop"
+ offset="100%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1; 2"
+ />
+ </stop>
+ </lineargradient>
+ </defs>
+ </svg>
+</div>
`;
exports[`Resizable Skeleton Loader with custom settings renders the correct position, and size percentages for bars and labels with different settings 1`] = `
-<svg
- class="gl-skeleton-loader"
- preserveAspectRatio="xMidYMid meet"
- version="1.1"
- viewBox="0 0 400 130"
+<div
+ class="gl-px-8"
>
- <rect
- clip-path="url(#-idClip)"
- height="130"
- style="fill: url(#-idGradient);"
- width="400"
- x="0"
- y="0"
- />
- <defs>
- <clippath
- id="-idClip"
- >
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="30%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="60%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="90%"
- />
-
- <rect
- data-testid="skeleton-chart-bar"
- height="5%"
- rx="0.6%"
- width="3%"
- x="6.0625%"
- y="85%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="7%"
- rx="0.6%"
- width="3%"
- x="18.1875%"
- y="83%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="9%"
- rx="0.6%"
- width="3%"
- x="30.3125%"
- y="81%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="14%"
- rx="0.6%"
- width="3%"
- x="42.4375%"
- y="76%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="21%"
- rx="0.6%"
- width="3%"
- x="54.5625%"
- y="69%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="35%"
- rx="0.6%"
- width="3%"
- x="66.6875%"
- y="55%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="50%"
- rx="0.6%"
- width="3%"
- x="78.8125%"
- y="40%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="80%"
- rx="0.6%"
- width="3%"
- x="90.9375%"
- y="10%"
- />
-
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="4.0625%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="16.1875%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="28.3125%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="40.4375%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="52.5625%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="64.6875%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="76.8125%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="88.9375%"
- y="98%"
- />
- </clippath>
- <lineargradient
- id="-idGradient"
- >
- <stop
- class="primary-stop"
- offset="0%"
+ <svg
+ class="gl-skeleton-loader"
+ preserveAspectRatio="xMidYMid meet"
+ version="1.1"
+ viewBox="0 0 400 130"
+ >
+ <rect
+ clip-path="url(#-idClip)"
+ height="130"
+ style="fill: url(#-idGradient);"
+ width="400"
+ x="0"
+ y="0"
+ />
+ <defs>
+ <clippath
+ id="-idClip"
>
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-2; 1"
- />
- </stop>
- <stop
- class="secondary-stop"
- offset="50%"
- >
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-1.5; 1.5"
- />
- </stop>
- <stop
- class="primary-stop"
- offset="100%"
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="30%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="60%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="90%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="5%"
+ rx="0.6%"
+ width="3%"
+ x="6.0625%"
+ y="85%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="7%"
+ rx="0.6%"
+ width="3%"
+ x="18.1875%"
+ y="83%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="9%"
+ rx="0.6%"
+ width="3%"
+ x="30.3125%"
+ y="81%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="14%"
+ rx="0.6%"
+ width="3%"
+ x="42.4375%"
+ y="76%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="21%"
+ rx="0.6%"
+ width="3%"
+ x="54.5625%"
+ y="69%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="35%"
+ rx="0.6%"
+ width="3%"
+ x="66.6875%"
+ y="55%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="50%"
+ rx="0.6%"
+ width="3%"
+ x="78.8125%"
+ y="40%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="80%"
+ rx="0.6%"
+ width="3%"
+ x="90.9375%"
+ y="10%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="4.0625%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="16.1875%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="28.3125%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="40.4375%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="52.5625%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="64.6875%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="76.8125%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="88.9375%"
+ y="98%"
+ />
+ </clippath>
+ <lineargradient
+ id="-idGradient"
>
- <animate
- attributeName="offset"
- dur="1s"
- repeatCount="indefinite"
- values="-1; 2"
- />
- </stop>
- </lineargradient>
- </defs>
-</svg>
+ <stop
+ class="primary-stop"
+ offset="0%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-2; 1"
+ />
+ </stop>
+ <stop
+ class="secondary-stop"
+ offset="50%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1.5; 1.5"
+ />
+ </stop>
+ <stop
+ class="primary-stop"
+ offset="100%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1; 2"
+ />
+ </stop>
+ </lineargradient>
+ </defs>
+ </svg>
+</div>
`;
diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb
index 8d2806cbef6..176585e2ded 100644
--- a/spec/helpers/notifications_helper_spec.rb
+++ b/spec/helpers/notifications_helper_spec.rb
@@ -4,12 +4,12 @@ require 'spec_helper'
RSpec.describe NotificationsHelper do
describe 'notification_icon' do
- it { expect(notification_icon(:disabled)).to match('class="fa fa-microphone-slash fa-fw"') }
- it { expect(notification_icon(:owner_disabled)).to match('class="fa fa-microphone-slash fa-fw"') }
- it { expect(notification_icon(:participating)).to match('class="fa fa-volume-up fa-fw"') }
- it { expect(notification_icon(:mention)).to match('class="fa fa-at fa-fw"') }
- it { expect(notification_icon(:global)).to match('class="fa fa-globe fa-fw"') }
- it { expect(notification_icon(:watch)).to match('class="fa fa-eye fa-fw"') }
+ it { expect(notification_icon(:disabled)).to match('data-testid="notifications-off-icon"') }
+ it { expect(notification_icon(:owner_disabled)).to match('data-testid="notifications-off-icon"') }
+ it { expect(notification_icon(:participating)).to match('data-testid="notifications-icon"') }
+ it { expect(notification_icon(:mention)).to match('data-testid="at-icon"') }
+ it { expect(notification_icon(:global)).to match('data-testid="earth-icon') }
+ it { expect(notification_icon(:watch)).to match('data-testid="eye-icon"') }
end
describe 'notification_title' do
diff --git a/spec/lib/backup/artifacts_spec.rb b/spec/lib/backup/artifacts_spec.rb
new file mode 100644
index 00000000000..2a3f1949ba5
--- /dev/null
+++ b/spec/lib/backup/artifacts_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::Artifacts do
+ let(:progress) { StringIO.new }
+
+ subject(:backup) { described_class.new(progress) }
+
+ describe '#initialize' do
+ it 'uses the correct upload dir' do
+ Dir.mktmpdir do |tmpdir|
+ allow(JobArtifactUploader).to receive(:root) { "#{tmpdir}" }
+
+ expect(backup.app_files_dir).to eq("#{tmpdir}")
+ end
+ end
+ end
+
+ describe '#dump' do
+ before do
+ allow(File).to receive(:realpath).with('/var/gitlab-artifacts').and_return('/var/gitlab-artifacts')
+ allow(File).to receive(:realpath).with('/var/gitlab-artifacts/..').and_return('/var')
+ allow(JobArtifactUploader).to receive(:root) { '/var/gitlab-artifacts' }
+ end
+
+ it 'uses the correct artifact dir' do
+ expect(backup.app_files_dir).to eq('/var/gitlab-artifacts')
+ end
+
+ it 'excludes tmp from backup tar' do
+ expect(backup).to receive(:tar).and_return('blabla-tar')
+ expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/gitlab-artifacts -cf - .), 'gzip -c -1'], any_args)
+ backup.dump
+ end
+ end
+end
diff --git a/spec/lib/backup/files_spec.rb b/spec/lib/backup/files_spec.rb
index a7374b82ce0..c2dbaac7f15 100644
--- a/spec/lib/backup/files_spec.rb
+++ b/spec/lib/backup/files_spec.rb
@@ -14,6 +14,8 @@ RSpec.describe Backup::Files do
allow(File).to receive(:exist?).and_return(true)
allow(File).to receive(:realpath).with("/var/gitlab-registry").and_return("/var/gitlab-registry")
allow(File).to receive(:realpath).with("/var/gitlab-registry/..").and_return("/var")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages").and_return("/var/gitlab-pages")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages/..").and_return("/var")
allow_any_instance_of(String).to receive(:color) do |string, _color|
string
@@ -82,4 +84,48 @@ RSpec.describe Backup::Files do
end
end
end
+
+ describe '#dump' do
+ subject { described_class.new('pages', '/var/gitlab-pages', excludes: ['@pages.tmp']) }
+
+ before do
+ allow(subject).to receive(:run_pipeline!).and_return(true)
+ end
+
+ it 'raises no errors' do
+ expect { subject.dump }.not_to raise_error
+ end
+
+ it 'excludes tmp dirs from archive' do
+ expect(subject).to receive(:tar).and_return('blabla-tar')
+
+ expect(subject).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./@pages.tmp -C /var/gitlab-pages -cf - .), 'gzip -c -1'], any_args)
+ subject.dump
+ end
+
+ describe 'with STRATEGY=copy' do
+ before do
+ stub_env('STRATEGY', 'copy')
+ end
+
+ it 'excludes tmp dirs from rsync' do
+ allow(Gitlab.config.backup).to receive(:path) { '/var/gitlab-backup' }
+ allow(File).to receive(:realpath).with("/var/gitlab-backup").and_return("/var/gitlab-backup")
+
+ expect(Gitlab::Popen).to receive(:popen).with(%w(rsync -a --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup)).and_return(['', 0])
+
+ subject.dump
+ end
+ end
+
+ describe '#exclude_dirs' do
+ it 'prepends a leading dot slash to tar excludes' do
+ expect(subject.exclude_dirs(:tar)).to eq(['--exclude=lost+found', '--exclude=./@pages.tmp'])
+ end
+
+ it 'prepends a leading slash to rsync excludes' do
+ expect(subject.exclude_dirs(:rsync)).to eq(['--exclude=lost+found', '--exclude=/@pages.tmp'])
+ end
+ end
+ end
end
diff --git a/spec/lib/backup/pages_spec.rb b/spec/lib/backup/pages_spec.rb
new file mode 100644
index 00000000000..59df4d1adf7
--- /dev/null
+++ b/spec/lib/backup/pages_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::Pages do
+ let(:progress) { StringIO.new }
+
+ subject { described_class.new(progress) }
+
+ before do
+ allow(File).to receive(:realpath).with("/var/gitlab-pages").and_return("/var/gitlab-pages")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages/..").and_return("/var")
+ end
+
+ describe '#dump' do
+ it 'uses the correct pages dir' do
+ allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
+
+ expect(subject.app_files_dir).to eq('/var/gitlab-pages')
+ end
+
+ it 'excludes tmp from backup tar' do
+ allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
+
+ expect(subject).to receive(:tar).and_return('blabla-tar')
+ expect(subject).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./@pages.tmp -C /var/gitlab-pages -cf - .), 'gzip -c -1'], any_args)
+ subject.dump
+ end
+ end
+end
diff --git a/spec/lib/backup/uploads_spec.rb b/spec/lib/backup/uploads_spec.rb
index 7c2d715b580..678b670db34 100644
--- a/spec/lib/backup/uploads_spec.rb
+++ b/spec/lib/backup/uploads_spec.rb
@@ -18,4 +18,22 @@ RSpec.describe Backup::Uploads do
end
end
end
+
+ describe '#dump' do
+ before do
+ allow(File).to receive(:realpath).with('/var/uploads').and_return('/var/uploads')
+ allow(File).to receive(:realpath).with('/var/uploads/..').and_return('/var')
+ allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' }
+ end
+
+ it 'uses the correct upload dir' do
+ expect(backup.app_files_dir).to eq('/var/uploads')
+ end
+
+ it 'excludes tmp from backup tar' do
+ expect(backup).to receive(:tar).and_return('blabla-tar')
+ expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/uploads -cf - .), 'gzip -c -1'], any_args)
+ backup.dump
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index 7d8fb183dbb..e7b6c910b8a 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -208,4 +208,47 @@ RSpec.describe Banzai::Filter::ExternalIssueReferenceFilter do
end
end
end
+
+ context "ewm project" do
+ let_it_be(:project) { create(:ewm_project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "rtcwi keyword" do
+ let(:issue) { ExternalIssue.new("rtcwi 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "workitem keyword" do
+ let(:issue) { ExternalIssue.new("workitem 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "defect keyword" do
+ let(:issue) { ExternalIssue.new("defect 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "task keyword" do
+ let(:issue) { ExternalIssue.new("task 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "bug keyword" do
+ let(:issue) { ExternalIssue.new("bug 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index bfdc6c959d3..5f691799e9c 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -365,6 +365,7 @@ project:
- youtrack_service
- custom_issue_tracker_service
- bugzilla_service
+- ewm_service
- external_wiki_service
- mock_ci_service
- mock_deployment_service
diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
index c93fc2c17f1..f881da71251 100644
--- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.categories' do
it 'gets all unique category names' do
- expect(described_class.categories).to contain_exactly('analytics', 'compliance', 'ide_edit', 'search', 'source_code', 'incident_management')
+ expect(described_class.categories).to contain_exactly('analytics', 'compliance', 'ide_edit', 'search', 'source_code', 'incident_management', 'issues_edit')
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..479fe36bcdd
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_gitlab_redis_shared_state do
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:user3) { build(:user, id: 3) }
+ let(:time) { Time.zone.now }
+
+ shared_examples 'tracks and counts action' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ def count_unique(date_from:, date_to:)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to)
+ end
+
+ specify do
+ aggregate_failures do
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user2)).to be_truthy
+ expect(track_action(author: user3, time: time - 3.days)).to be_truthy
+
+ expect(count_unique(date_from: time, date_to: time)).to eq(2)
+ expect(count_unique(date_from: time - 5.days, date_to: 1.day.since(time))).to eq(3)
+ end
+ end
+
+ it 'does not track edit actions if author is not present' do
+ expect(track_action(author: nil)).to be_nil
+ end
+
+ context 'when feature flag track_issue_activity_actions is disabled' do
+ it 'does not track edit actions' do
+ stub_feature_flags(track_issue_activity_actions: false)
+
+ expect(track_action(author: user1)).to be_nil
+ end
+ end
+ end
+
+ context 'for Issue title edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_TITLE_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_title_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue description edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_DESCRIPTION_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_description_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue assignee edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_ASSIGNEE_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_assignee_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue make confidential actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_MADE_CONFIDENTIAL }
+
+ def track_action(params)
+ described_class.track_issue_made_confidential_action(params)
+ end
+ end
+ end
+
+ context 'for Issue make visible actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_MADE_VISIBLE }
+
+ def track_action(params)
+ described_class.track_issue_made_visible_action(params)
+ end
+ end
+ end
+
+ it 'can return the count of actions per user deduplicated', :aggregate_failures do
+ described_class.track_issue_title_changed_action(author: user1)
+ described_class.track_issue_description_changed_action(author: user1)
+ described_class.track_issue_assignee_changed_action(author: user1)
+ described_class.track_issue_title_changed_action(author: user2, time: time - 2.days)
+ described_class.track_issue_title_changed_action(author: user3, time: time - 3.days)
+ described_class.track_issue_description_changed_action(author: user3, time: time - 3.days)
+ described_class.track_issue_assignee_changed_action(author: user3, time: time - 3.days)
+
+ events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(described_class::ISSUE_CATEGORY)
+ today_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time, end_date: time)
+ week_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time - 5.days, end_date: 1.day.since(time))
+
+ expect(today_count).to eq(1)
+ expect(week_count).to eq(3)
+ end
+end
diff --git a/spec/models/alert_management/alert_spec.rb b/spec/models/alert_management/alert_spec.rb
index f937a879400..87aeb3d78c0 100644
--- a/spec/models/alert_management/alert_spec.rb
+++ b/spec/models/alert_management/alert_spec.rb
@@ -332,33 +332,6 @@ RSpec.describe AlertManagement::Alert do
end
end
- describe '#details' do
- let(:payload) do
- {
- 'title' => 'Details title',
- 'custom' => {
- 'alert' => {
- 'fields' => %w[one two]
- }
- },
- 'yet' => {
- 'another' => 'field'
- }
- }
- end
-
- let(:alert) { build(:alert_management_alert, project: project, title: 'Details title', payload: payload) }
-
- subject { alert.details }
-
- it 'renders the payload as inline hash' do
- is_expected.to eq(
- 'custom.alert.fields' => %w[one two],
- 'yet.another' => 'field'
- )
- end
- end
-
describe '#to_reference' do
it { expect(triggered_alert.to_reference).to eq('') }
end
diff --git a/spec/models/project_services/ewm_service_spec.rb b/spec/models/project_services/ewm_service_spec.rb
new file mode 100644
index 00000000000..311c456569e
--- /dev/null
+++ b/spec/models/project_services/ewm_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe EwmService do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+
+ describe "ReferencePatternValidation" do
+ it "extracts bug" do
+ expect(described_class.reference_pattern.match("This is bug 123")[:issue]).to eq("bug 123")
+ end
+
+ it "extracts task" do
+ expect(described_class.reference_pattern.match("This is task 123.")[:issue]).to eq("task 123")
+ end
+
+ it "extracts work item" do
+ expect(described_class.reference_pattern.match("This is work item 123 now")[:issue]).to eq("work item 123")
+ end
+
+ it "extracts workitem" do
+ expect(described_class.reference_pattern.match("workitem 123 at the beginning")[:issue]).to eq("workitem 123")
+ end
+
+ it "extracts defect" do
+ expect(described_class.reference_pattern.match("This is defect 123 defect")[:issue]).to eq("defect 123")
+ end
+
+ it "extracts rtcwi" do
+ expect(described_class.reference_pattern.match("This is rtcwi 123")[:issue]).to eq("rtcwi 123")
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 546b869ffd9..77b8b22e3f3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -61,6 +61,7 @@ RSpec.describe Project do
it { is_expected.to have_one(:youtrack_service) }
it { is_expected.to have_one(:custom_issue_tracker_service) }
it { is_expected.to have_one(:bugzilla_service) }
+ it { is_expected.to have_one(:ewm_service) }
it { is_expected.to have_one(:external_wiki_service) }
it { is_expected.to have_one(:confluence_service) }
it { is_expected.to have_one(:project_feature) }
diff --git a/spec/presenters/alert_management/alert_presenter_spec.rb b/spec/presenters/alert_management/alert_presenter_spec.rb
index 365dc84ff53..3b7920dfd5e 100644
--- a/spec/presenters/alert_management/alert_presenter_spec.rb
+++ b/spec/presenters/alert_management/alert_presenter_spec.rb
@@ -9,7 +9,14 @@ RSpec.describe AlertManagement::AlertPresenter do
{
'title' => 'Alert title',
'start_time' => '2020-04-27T10:10:22.265949279Z',
- 'custom' => { 'param' => 73 }
+ 'custom' => {
+ 'alert' => {
+ 'fields' => %w[one two]
+ }
+ },
+ 'yet' => {
+ 'another' => 73
+ }
}
end
@@ -37,7 +44,10 @@ RSpec.describe AlertManagement::AlertPresenter do
#### Alert Details
- **custom.param:** 73
+ **title:** Alert title#{markdown_line_break}
+ **start_time:** 2020-04-27T10:10:22.265949279Z#{markdown_line_break}
+ **custom.alert.fields:** ["one", "two"]#{markdown_line_break}
+ **yet.another:** 73
MARKDOWN
)
end
@@ -54,4 +64,17 @@ RSpec.describe AlertManagement::AlertPresenter do
expect(presenter.details_url).to match(%r{#{project.web_url}/-/alert_management/#{alert.iid}/details})
end
end
+
+ describe '#details' do
+ subject { presenter.details }
+
+ it 'renders the payload as inline hash' do
+ is_expected.to eq(
+ 'title' => 'Alert title',
+ 'start_time' => '2020-04-27T10:10:22.265949279Z',
+ 'custom.alert.fields' => %w[one two],
+ 'yet.another' => 73
+ )
+ end
+ end
end
diff --git a/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb b/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb
index 8ff51b9a8e1..74c77b70e5a 100644
--- a/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb
+++ b/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb
@@ -38,7 +38,11 @@ RSpec.describe AlertManagement::PrometheusAlertPresenter do
#### Alert Details
- **custom annotation:** custom annotation value
+ **annotations.custom annotation:** custom annotation value#{markdown_line_break}
+ **annotations.gitlab_incident_markdown:** **`markdown example`**#{markdown_line_break}
+ **annotations.title:** Alert title#{markdown_line_break}
+ **startsAt:** 2020-04-27T10:10:22.265949279Z#{markdown_line_break}
+ **generatorURL:** http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1
---
diff --git a/spec/presenters/projects/prometheus/alert_presenter_spec.rb b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
index 1c37e551385..4f1b1931fb9 100644
--- a/spec/presenters/projects/prometheus/alert_presenter_spec.rb
+++ b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
@@ -65,32 +65,25 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
**Start time:** #{presenter.start_time}
- MARKDOWN
- )
- end
- end
-
- context 'with annotations' do
- before do
- payload['annotations'] = { 'title' => 'Alert Title', 'foo' => 'value1', 'bar' => 'value2' }
- end
-
- it do
- is_expected.to eq(
- <<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}
-
#### Alert Details
- **foo:** value1#{markdown_line_break}
- **bar:** value2
+ **startsAt:** #{presenter.starts_at_raw}
MARKDOWN
)
end
end
- context 'with full query' do
+ context 'with optional attributes' do
before do
+ payload['annotations'] = {
+ 'title' => 'Alert Title',
+ 'foo' => 'value1',
+ 'bar' => 'value2',
+ 'description' => 'Alert Description',
+ 'monitoring_tool' => 'monitoring_tool_name',
+ 'service' => 'service_name',
+ 'hosts' => ['http://localhost:3000', 'http://localhost:3001']
+ }
payload['generatorURL'] = 'http://host?g0.expr=query'
end
@@ -98,72 +91,52 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
is_expected.to eq(
<<~MARKDOWN.chomp
**Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `query`
+ **full_query:** `query`#{markdown_line_break}
+ **Service:** service_name#{markdown_line_break}
+ **Monitoring tool:** monitoring_tool_name#{markdown_line_break}
+ **Hosts:** http://localhost:3000 http://localhost:3001
+ #### Alert Details
+
+ **annotations.hosts:** ["http://localhost:3000", "http://localhost:3001"]#{markdown_line_break}
+ **annotations.service:** service_name#{markdown_line_break}
+ **annotations.monitoring_tool:** monitoring_tool_name#{markdown_line_break}
+ **annotations.description:** Alert Description#{markdown_line_break}
+ **annotations.bar:** value2#{markdown_line_break}
+ **annotations.foo:** value1#{markdown_line_break}
+ **annotations.title:** Alert Title#{markdown_line_break}
+ **generatorURL:** http://host?g0.expr=query#{markdown_line_break}
+ **startsAt:** #{presenter.starts_at_raw}
MARKDOWN
)
end
end
- context 'with the Generic Alert parameters' do
- let(:generic_alert_params) do
- {
- 'title' => 'The Generic Alert Title',
- 'description' => 'The Generic Alert Description',
- 'monitoring_tool' => 'monitoring_tool_name',
- 'service' => 'service_name',
- 'hosts' => ['http://localhost:3000', 'http://localhost:3001']
- }
- end
-
+ context 'when hosts is a string' do
before do
- payload['annotations'] = generic_alert_params
+ payload['annotations'] = { 'hosts' => 'http://localhost:3000' }
end
it do
is_expected.to eq(
<<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Service:** service_name#{markdown_line_break}
- **Monitoring tool:** monitoring_tool_name#{markdown_line_break}
- **Hosts:** http://localhost:3000 http://localhost:3001
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Hosts:** http://localhost:3000
- #### Alert Details
+ #### Alert Details
- **description:** The Generic Alert Description
+ **annotations.hosts:** http://localhost:3000#{markdown_line_break}
+ **startsAt:** #{presenter.starts_at_raw}
MARKDOWN
)
end
-
- context 'when hosts is a string' do
- before do
- payload['annotations'] = { 'hosts' => 'http://localhost:3000' }
- end
-
- it do
- is_expected.to eq(
- <<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Hosts:** http://localhost:3000
-
- MARKDOWN
- )
- end
- end
end
context 'with embedded metrics' do
let(:starts_at) { '2018-03-12T09:06:00Z' }
shared_examples_for 'markdown with metrics embed' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `avg(metric) > 1.0`
-
- [](#{presenter.metrics_dashboard_url})
- MARKDOWN
- end
+ let(:embed_regex) { /\n\[\]\(#{Regexp.quote(presenter.metrics_dashboard_url)}\)\z/ }
context 'without a starting time available' do
around do |example|
@@ -174,11 +147,11 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload.delete('startsAt')
end
- it { is_expected.to eq(expected_markdown) }
+ it { is_expected.to match(embed_regex) }
end
context 'with a starting time available' do
- it { is_expected.to eq(expected_markdown) }
+ it { is_expected.to match(embed_regex) }
end
end
@@ -208,12 +181,8 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
end
context 'when not enough information is present for an embed' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `avg(metric) > 1.0`
-
- MARKDOWN
+ shared_examples_for 'does not include an embed' do
+ it { is_expected.not_to match(/\[\]\(.+\)/) }
end
context 'without title' do
@@ -221,7 +190,7 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload['annotations'].delete('title')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
context 'without environment' do
@@ -229,22 +198,15 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload['labels'].delete('gitlab_environment_name')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
context 'without full_query' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- **Start time:** #{presenter.start_time}
-
- MARKDOWN
- end
-
before do
payload.delete('generatorURL')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
end
end
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index 7bb73e9664b..1ae9b0d548d 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -60,25 +60,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
-
- it 'returns random one' do
- get api("/projects/#{project.id}/variables/key1", user)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['key']).to eq('key1')
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
@@ -232,25 +217,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
-
- it 'updates random one' do
- put api("/projects/#{project.id}/variables/key1", user), params: { value: 'new_val' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['value']).to eq('new_val')
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
@@ -312,26 +282,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
-
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- it 'deletes random one' do
- expect do
- delete api("/projects/#{project.id}/variables/key1", user), params: { 'filter[environment_scope]': 'production' }
-
- expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.variables.count}.by(-1)
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
diff --git a/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb b/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
index 8dbd90afa5e..fa4acc62226 100644
--- a/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
+++ b/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
@@ -42,14 +42,28 @@ RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys, type: :ruboc
context 'with foreign key' do
context 'with just one foreign key' do
context 'when the foreign_key targets a high traffic table' do
- it 'does not register any offenses' do
- expect_no_offenses(<<~RUBY)
- def up
- create_table(:foo) do |t|
- t.references :project, "foreign_key" => { on_delete: 'cascade', to_table: 'projects' }
+ context 'when the foreign_key has to_table option set' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :project, "foreign_key" => { on_delete: 'cascade', to_table: 'projects' }
+ end
end
- end
- RUBY
+ RUBY
+ end
+ end
+
+ context 'when the foreign_key does not have to_table option set' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :project, foreign_key: { on_delete: 'cascade' }
+ end
+ end
+ RUBY
+ end
end
end
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
index 487c38da7da..c9910487798 100644
--- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
@@ -124,3 +124,16 @@ end
def get_textarea_height
page.evaluate_script('document.getElementById("merge_request_description").offsetHeight')
end
+
+RSpec.shared_examples 'an editable merge request with reviewers' do
+ it 'updates merge request', :js do
+ find('.js-reviewer-search').click
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+ expect(find('input[name="merge_request[reviewer_ids][]"]', visible: false).value).to match(user.id.to_s)
+ page.within '.js-reviewer-search' do
+ expect(page).to have_content user.name
+ end
+ end
+end
diff --git a/spec/views/projects/merge_requests/edit.html.haml_spec.rb b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
index 55a74dc8229..215d404e395 100644
--- a/spec/views/projects/merge_requests/edit.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe 'projects/merge_requests/edit.html.haml' do
target_project: project,
author: user,
assignees: [user],
+ reviewers: [user],
milestone: milestone)
end