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>2022-12-16 12:09:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-16 12:09:38 +0300
commitbc9b43904d491c7b864c8fb6ba06ae0f6625db0d (patch)
treeca0a5ae3bbbf98530707b96a7db08d1bd773b429 /spec
parent10476ea7d8253d8462e092ed95aedc01204238bc (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/branches/new_branch_ref_dropdown_spec.rb69
-rw-r--r--spec/features/projects/branches/user_creates_branch_spec.rb6
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_link_child_metadata_spec.js67
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js40
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js61
-rw-r--r--spec/frontend/work_items/mock_data.js65
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb7
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_note_spec.rb115
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb84
-rw-r--r--spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb5
-rw-r--r--spec/migrations/20221209110935_fix_update_import_sources_on_application_settings_spec.rb34
-rw-r--r--spec/support/helpers/features/branches_helpers.rb10
-rw-r--r--spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb1
13 files changed, 444 insertions, 120 deletions
diff --git a/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb
index fb68195362a..eb370cfc1fc 100644
--- a/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb
+++ b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe 'New Branch Ref Dropdown', :js, feature_category: :projects do
let(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
- let(:toggle) { find('.create-from .dropdown-menu-toggle') }
+ let(:sha) { project.commit.sha }
+ let(:toggle) { find('.ref-selector') }
before do
project.add_maintainer(user)
@@ -14,37 +15,75 @@ RSpec.describe 'New Branch Ref Dropdown', :js, feature_category: :projects do
visit new_project_branch_path(project)
end
- it 'filters a list of branches and tags' do
+ it 'finds a tag in a list' do
+ tag_name = 'v1.0.0'
+
toggle.click
- filter_by('v1.0.0')
+ filter_by(tag_name)
+
+ wait_for_requests
+
+ expect(items_count(tag_name)).to be(1)
- expect(items_count).to be(1)
+ item(tag_name).click
- filter_by('video')
+ expect(toggle).to have_content tag_name
+ end
+
+ it 'finds a branch in a list' do
+ branch_name = 'audio'
- expect(items_count).to be(1)
+ toggle.click
- find('.create-from .dropdown-content li').click
+ filter_by(branch_name)
- expect(toggle).to have_content 'video'
+ wait_for_requests
+
+ expect(items_count(branch_name)).to be(1)
+
+ item(branch_name).click
+
+ expect(toggle).to have_content branch_name
end
- it 'accepts a manually entered commit SHA' do
+ it 'finds a commit in a list' do
toggle.click
- filter_by('somecommitsha')
+ filter_by(sha)
+
+ wait_for_requests
+
+ sha_short = sha[0, 7]
- find('.create-from input[type=search]').send_keys(:enter)
+ expect(items_count(sha_short)).to be(1)
+
+ item(sha_short).click
+
+ expect(toggle).to have_content sha_short
+ end
+
+ it 'shows no results when there is no branch, tag or commit sha found' do
+ non_existing_ref = 'non_existing_branch_name'
+
+ toggle.click
+
+ filter_by(non_existing_ref)
+
+ wait_for_requests
+
+ expect(find('.gl-dropdown-contents')).not_to have_content(non_existing_ref)
+ end
- expect(toggle).to have_content 'somecommitsha'
+ def item(ref_name)
+ find('li', text: ref_name, match: :prefer_exact)
end
- def items_count
- all('.create-from .dropdown-content li').length
+ def items_count(ref_name)
+ all('li', text: ref_name, match: :prefer_exact).length
end
def filter_by(filter_text)
- fill_in 'Filter by Git revision', with: filter_text
+ fill_in _('Search by Git revision'), with: filter_text
end
end
diff --git a/spec/features/projects/branches/user_creates_branch_spec.rb b/spec/features/projects/branches/user_creates_branch_spec.rb
index bf7669e9d0c..60bd77393e9 100644
--- a/spec/features/projects/branches/user_creates_branch_spec.rb
+++ b/spec/features/projects/branches/user_creates_branch_spec.rb
@@ -81,11 +81,7 @@ RSpec.describe 'User creates branch', :js, feature_category: :projects do
it 'does not create new branch' do
invalid_branch_name = '1.0 stable'
- fill_in('branch_name', with: invalid_branch_name)
- page.find('body').click # defocus the branch_name input
-
- select_branch('master')
- click_button('Create branch')
+ create_branch(invalid_branch_name)
expect(page).to have_content('Branch name is invalid')
expect(page).to have_content("can't contain spaces")
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_link_child_metadata_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_link_child_metadata_spec.js
new file mode 100644
index 00000000000..47489d4796b
--- /dev/null
+++ b/spec/frontend/work_items/components/work_item_links/work_item_link_child_metadata_spec.js
@@ -0,0 +1,67 @@
+import { GlLabel, GlAvatarsInline } from '@gitlab/ui';
+
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import ItemMilestone from '~/issuable/components/issue_milestone.vue';
+import WorkItemLinkChildMetadata from '~/work_items/components/work_item_links/work_item_link_child_metadata.vue';
+
+import { mockMilestone, mockAssignees, mockLabels } from '../../mock_data';
+
+describe('WorkItemLinkChildMetadata', () => {
+ let wrapper;
+
+ const createComponent = ({
+ allowsScopedLabels = true,
+ milestone = mockMilestone,
+ assignees = mockAssignees,
+ labels = mockLabels,
+ } = {}) => {
+ wrapper = shallowMountExtended(WorkItemLinkChildMetadata, {
+ propsData: {
+ allowsScopedLabels,
+ milestone,
+ assignees,
+ labels,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders milestone link button', () => {
+ const milestoneLink = wrapper.findComponent(ItemMilestone);
+
+ expect(milestoneLink.exists()).toBe(true);
+ expect(milestoneLink.props('milestone')).toEqual(mockMilestone);
+ });
+
+ it('renders avatars for assignees', () => {
+ const avatars = wrapper.findComponent(GlAvatarsInline);
+
+ expect(avatars.exists()).toBe(true);
+ expect(avatars.props()).toMatchObject({
+ avatars: mockAssignees,
+ collapsed: true,
+ maxVisible: 2,
+ avatarSize: 24,
+ badgeTooltipProp: 'name',
+ badgeSrOnlyText: '',
+ });
+ });
+
+ it('renders labels', () => {
+ const labels = wrapper.findAllComponents(GlLabel);
+ const mockLabel = mockLabels[0];
+
+ expect(labels).toHaveLength(mockLabels.length);
+ expect(labels.at(0).props()).toMatchObject({
+ title: mockLabel.title,
+ backgroundColor: mockLabel.color,
+ description: mockLabel.description,
+ scoped: false,
+ });
+ expect(labels.at(1).props('scoped')).toBe(true); // Second label is scoped
+ });
+});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
index 3a8e785bc80..73d498ad055 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlIcon } from '@gitlab/ui';
+import { GlIcon } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -9,6 +9,7 @@ import { createAlert } from '~/flash';
import RichTimestampTooltip from '~/vue_shared/components/rich_timestamp_tooltip.vue';
import getWorkItemTreeQuery from '~/work_items/graphql/work_item_tree.query.graphql';
+import WorkItemLinkChildMetadata from '~/work_items/components/work_item_links/work_item_link_child_metadata.vue';
import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue';
import WorkItemLinksMenu from '~/work_items/components/work_item_links/work_item_links_menu.vue';
import WorkItemTreeChildren from '~/work_items/components/work_item_links/work_item_tree_children.vue';
@@ -21,8 +22,12 @@ import {
import {
workItemTask,
workItemObjectiveWithChild,
+ workItemObjectiveNoMetadata,
confidentialWorkItemTask,
closedWorkItemTask,
+ mockMilestone,
+ mockAssignees,
+ mockLabels,
workItemHierarchyTreeResponse,
workItemHierarchyTreeFailureResponse,
} from '../../mock_data';
@@ -101,7 +106,7 @@ describe('WorkItemLinkChild', () => {
beforeEach(() => {
createComponent();
- titleEl = wrapper.findComponent(GlButton);
+ titleEl = wrapper.findByTestId('item-title');
});
it('renders item title', () => {
@@ -129,6 +134,37 @@ describe('WorkItemLinkChild', () => {
});
});
+ describe('item metadata', () => {
+ const findMetadataComponent = () => wrapper.findComponent(WorkItemLinkChildMetadata);
+
+ beforeEach(() => {
+ createComponent({
+ childItem: workItemObjectiveWithChild,
+ workItemType: WORK_ITEM_TYPE_VALUE_OBJECTIVE,
+ });
+ });
+
+ it('renders item metadata component when item has metadata present', () => {
+ const metadataEl = findMetadataComponent();
+ expect(metadataEl.exists()).toBe(true);
+ expect(metadataEl.props()).toMatchObject({
+ allowsScopedLabels: true,
+ milestone: mockMilestone,
+ assignees: mockAssignees,
+ labels: mockLabels,
+ });
+ });
+
+ it('does not render item metadata component when item has no metadata present', () => {
+ createComponent({
+ childItem: workItemObjectiveNoMetadata,
+ workItemType: WORK_ITEM_TYPE_VALUE_OBJECTIVE,
+ });
+
+ expect(findMetadataComponent().exists()).toBe(false);
+ });
+ });
+
describe('item menu', () => {
let itemMenuEl;
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
index cc2e174dfda..96211e12755 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
@@ -1,17 +1,26 @@
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+
+import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import WorkItemTree from '~/work_items/components/work_item_links/work_item_tree.vue';
import WorkItemLinksForm from '~/work_items/components/work_item_links/work_item_links_form.vue';
import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue';
import OkrActionsSplitButton from '~/work_items/components/work_item_links/okr_actions_split_button.vue';
+import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+
import {
FORM_TYPES,
WORK_ITEM_TYPE_ENUM_OBJECTIVE,
WORK_ITEM_TYPE_ENUM_KEY_RESULT,
} from '~/work_items/constants';
-import { childrenWorkItems } from '../../mock_data';
+import { childrenWorkItems, workItemObjectiveWithChild } from '../../mock_data';
describe('WorkItemTree', () => {
+ let getWorkItemQueryHandler;
let wrapper;
const findToggleButton = () => wrapper.findByTestId('toggle-tree');
@@ -21,10 +30,31 @@ describe('WorkItemTree', () => {
const findForm = () => wrapper.findComponent(WorkItemLinksForm);
const findWorkItemLinkChildItems = () => wrapper.findAllComponents(WorkItemLinkChild);
- const createComponent = ({ children = childrenWorkItems } = {}) => {
+ Vue.use(VueApollo);
+
+ const createComponent = ({
+ workItemType = 'Objective',
+ children = childrenWorkItems,
+ apolloProvider = null,
+ } = {}) => {
+ const mockWorkItemResponse = {
+ data: {
+ workItem: {
+ ...workItemObjectiveWithChild,
+ workItemType: {
+ ...workItemObjectiveWithChild.workItemType,
+ name: workItemType,
+ },
+ },
+ },
+ };
+ getWorkItemQueryHandler = jest.fn().mockResolvedValue(mockWorkItemResponse);
+
wrapper = shallowMountExtended(WorkItemTree, {
+ apolloProvider:
+ apolloProvider || createMockApollo([[workItemQuery, getWorkItemQueryHandler]]),
propsData: {
- workItemType: 'Objective',
+ workItemType,
workItemId: 'gid://gitlab/WorkItem/515',
children,
projectPath: 'test/project',
@@ -91,4 +121,27 @@ describe('WorkItemTree', () => {
expect(wrapper.emitted('removeChild')).toEqual([['gid://gitlab/WorkItem/2']]);
});
+
+ it.each`
+ description | workItemType | prefetch
+ ${'prefetches'} | ${'Issue'} | ${true}
+ ${'does not prefetch'} | ${'Objective'} | ${false}
+ `(
+ '$description work-item-link-child on mouseover when workItemType is "$workItemType"',
+ async ({ workItemType, prefetch }) => {
+ createComponent({ workItemType });
+ const firstChild = findWorkItemLinkChildItems().at(0);
+ firstChild.vm.$emit('mouseover', childrenWorkItems[0]);
+ await nextTick();
+ await waitForPromises();
+
+ jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+
+ if (prefetch) {
+ expect(getWorkItemQueryHandler).toHaveBeenCalled();
+ } else {
+ expect(getWorkItemQueryHandler).not.toHaveBeenCalled();
+ }
+ },
+ );
});
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index ed9c3f906b9..f7301701dc3 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -36,6 +36,16 @@ export const mockLabels = [
},
];
+export const mockMilestone = {
+ __typename: 'Milestone',
+ id: 'gid://gitlab/Milestone/30',
+ title: 'v4.0',
+ state: 'active',
+ expired: false,
+ startDate: '2022-10-17',
+ dueDate: '2022-10-24',
+};
+
export const workItemQueryResponse = {
data: {
workItem: {
@@ -359,11 +369,7 @@ export const workItemResponseFactory = ({
? {
__typename: 'WorkItemWidgetMilestone',
type: 'MILESTONE',
- milestone: {
- expired: false,
- id: 'gid://gitlab/Milestone/30',
- title: 'v4.0',
- },
+ milestone: mockMilestone,
}
: { type: 'MOCK TYPE' },
{
@@ -937,7 +943,17 @@ export const workItemObjectiveWithChild = {
iconName: 'issue-type-objective',
__typename: 'WorkItemType',
},
+ project: {
+ __typename: 'Project',
+ id: '1',
+ fullPath: 'test-project-path',
+ },
+ userPermissions: {
+ deleteWorkItem: true,
+ updateWorkItem: true,
+ },
title: 'Objective',
+ description: 'Objective description',
state: 'OPEN',
confidential: false,
createdAt: '2022-08-03T12:41:54Z',
@@ -946,12 +962,51 @@ export const workItemObjectiveWithChild = {
{
type: 'HIERARCHY',
hasChildren: true,
+ parent: null,
+ children: {
+ nodes: [],
+ },
__typename: 'WorkItemWidgetHierarchy',
},
+ {
+ type: 'MILESTONE',
+ __typename: 'WorkItemWidgetMilestone',
+ milestone: mockMilestone,
+ },
+ {
+ type: 'ASSIGNEES',
+ __typename: 'WorkItemWidgetAssignees',
+ canInviteMembers: true,
+ allowsMultipleAssignees: true,
+ assignees: {
+ __typename: 'UserCoreConnection',
+ nodes: mockAssignees,
+ },
+ },
+ {
+ type: 'LABELS',
+ __typename: 'WorkItemWidgetLabels',
+ allowsScopedLabels: true,
+ labels: {
+ __typename: 'LabelConnection',
+ nodes: mockLabels,
+ },
+ },
],
__typename: 'WorkItem',
};
+export const workItemObjectiveNoMetadata = {
+ ...workItemObjectiveWithChild,
+ widgets: [
+ {
+ type: 'HIERARCHY',
+ hasChildren: true,
+ __typename: 'WorkItemWidgetHierarchy',
+ },
+ ],
+};
+
export const workItemHierarchyTreeResponse = {
data: {
workItem: {
diff --git a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
index 1bcb7fec327..73ba49bf4ed 100644
--- a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
@@ -35,7 +35,8 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
end_line: end_line,
github_id: 1,
diff_hunk: diff_hunk,
- side: 'RIGHT'
+ side: 'RIGHT',
+ discussion_id: discussion_id
)
end
@@ -114,10 +115,6 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
.to receive(:database_id)
.and_return(merge_request.id)
end
-
- expect(Discussion)
- .to receive(:discussion_id)
- .and_return(discussion_id)
end
it_behaves_like 'diff notes without suggestion'
diff --git a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
index a656cd0d056..56fabe854f9 100644
--- a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
@@ -128,64 +128,6 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
end
end
- describe '#discussion_id' do
- before do
- note.project = project
- note.merge_request = merge_request
- end
-
- context 'when the note is a reply to a discussion' do
- it 'uses the cached value as the discussion_id only when responding an existing discussion' do
- expect(Discussion)
- .to receive(:discussion_id)
- .and_return('FIRST_DISCUSSION_ID', 'SECOND_DISCUSSION_ID')
-
- # Creates the first discussion id and caches its value
- expect(note.discussion_id)
- .to eq('FIRST_DISCUSSION_ID')
-
- reply_note = described_class.from_json_hash(
- 'note_id' => note.note_id + 1,
- 'in_reply_to_id' => note.note_id
- )
- reply_note.project = project
- reply_note.merge_request = merge_request
-
- # Reading from the cached value
- expect(reply_note.discussion_id)
- .to eq('FIRST_DISCUSSION_ID')
-
- new_discussion_note = described_class.from_json_hash(
- 'note_id' => note.note_id + 2,
- 'in_reply_to_id' => nil
- )
- new_discussion_note.project = project
- new_discussion_note.merge_request = merge_request
-
- # Because it's a new discussion, it must not use the cached value
- expect(new_discussion_note.discussion_id)
- .to eq('SECOND_DISCUSSION_ID')
- end
-
- context 'when cached value does not exist' do
- it 'falls back to generating a new discussion_id' do
- expect(Discussion)
- .to receive(:discussion_id)
- .and_return('NEW_DISCUSSION_ID')
-
- reply_note = described_class.from_json_hash(
- 'note_id' => note.note_id + 1,
- 'in_reply_to_id' => note.note_id
- )
- reply_note.project = project
- reply_note.merge_request = merge_request
-
- expect(reply_note.discussion_id).to eq('NEW_DISCUSSION_ID')
- end
- end
- end
- end
-
describe '#github_identifiers' do
it 'returns a hash with needed identifiers' do
expect(note.github_identifiers).to eq(
@@ -273,27 +215,40 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
end
describe '.from_api_response' do
- it_behaves_like 'a DiffNote representation' do
- let(:response) do
- {
- id: note_id,
- html_url: 'https://github.com/foo/bar/pull/42',
- path: 'README.md',
- commit_id: '123abc',
- original_commit_id: 'original123abc',
- side: side,
- user: user_data,
- diff_hunk: hunk,
- body: note_body,
- created_at: created_at,
- updated_at: updated_at,
- line: end_line,
- start_line: start_line,
- in_reply_to_id: in_reply_to_id
- }
- end
+ let(:response) do
+ {
+ id: note_id,
+ html_url: 'https://github.com/foo/bar/pull/42',
+ path: 'README.md',
+ commit_id: '123abc',
+ original_commit_id: 'original123abc',
+ side: side,
+ user: user_data,
+ diff_hunk: hunk,
+ body: note_body,
+ created_at: created_at,
+ updated_at: updated_at,
+ line: end_line,
+ start_line: start_line,
+ in_reply_to_id: in_reply_to_id
+ }
+ end
+
+ subject(:note) { described_class.from_api_response(response) }
+
+ it_behaves_like 'a DiffNote representation'
+
+ describe '#discussion_id' do
+ it 'finds or generates discussion_id value' do
+ discussion_id = 'discussion_id'
+ discussion_id_class = Gitlab::GithubImport::Representation::DiffNotes::DiscussionId
- subject(:note) { described_class.from_api_response(response) }
+ expect_next_instance_of(discussion_id_class, response) do |discussion_id_object|
+ expect(discussion_id_object).to receive(:find_or_generate).and_return(discussion_id)
+ end
+
+ expect(note.discussion_id).to eq(discussion_id)
+ end
end
end
@@ -302,6 +257,7 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
let(:hash) do
{
'note_id' => note_id,
+ 'html_url' => 'https://github.com/foo/bar/pull/42',
'noteable_type' => 'MergeRequest',
'noteable_id' => 42,
'file_path' => 'README.md',
@@ -315,7 +271,8 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
'updated_at' => updated_at.to_s,
'end_line' => end_line,
'start_line' => start_line,
- 'in_reply_to_id' => in_reply_to_id
+ 'in_reply_to_id' => in_reply_to_id,
+ 'discussion_id' => 'FIRST_DISCUSSION_ID'
}
end
diff --git a/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb b/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb
new file mode 100644
index 00000000000..64a16516e07
--- /dev/null
+++ b/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::DiscussionId, :clean_gitlab_redis_cache,
+ feature_category: :importers do
+ describe '#discussion_id' do
+ let(:hunk) do
+ '@@ -1 +1 @@
+ -Hello
+ +Hello world'
+ end
+
+ let(:note_id) { 1 }
+ let(:html_url) { 'https://github.com/foo/project_name/pull/42' }
+ let(:note) do
+ {
+ id: note_id,
+ html_url: html_url,
+ path: 'README.md',
+ commit_id: '123abc',
+ original_commit_id: 'original123abc',
+ side: 'RIGHT',
+ user: { id: 4, login: 'alice' },
+ diff_hunk: hunk,
+ body: 'Hello world',
+ created_at: Time.new(2017, 1, 1, 12, 10).utc,
+ updated_at: Time.new(2017, 1, 1, 12, 15).utc,
+ line: 23,
+ start_line: nil,
+ in_reply_to_id: nil
+ }
+ end
+
+ context 'when the note is not a reply to a discussion' do
+ subject(:discussion_id) { described_class.new(note).find_or_generate }
+
+ it 'generates and caches new discussion_id' do
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return('FIRST_DISCUSSION_ID')
+
+ expect(Gitlab::Cache::Import::Caching).to receive(:write).with(
+ "github-importer/discussion-id-map/project_name/42/#{note_id}",
+ 'FIRST_DISCUSSION_ID'
+ ).and_return('FIRST_DISCUSSION_ID')
+
+ expect(discussion_id).to eq('FIRST_DISCUSSION_ID')
+ end
+ end
+
+ context 'when the note is a reply to a discussion' do
+ let(:reply_note) do
+ {
+ note_id: note_id + 1,
+ in_reply_to_id: note_id,
+ html_url: html_url
+ }
+ end
+
+ subject(:discussion_id) { described_class.new(reply_note).find_or_generate }
+
+ it 'uses the cached value as the discussion_id' do
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return('FIRST_DISCUSSION_ID')
+
+ described_class.new(note).find_or_generate
+
+ expect(discussion_id).to eq('FIRST_DISCUSSION_ID')
+ end
+
+ context 'when cached value does not exist' do
+ it 'falls back to generating a new discussion_id' do
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return('NEW_DISCUSSION_ID')
+
+ expect(discussion_id).to eq('NEW_DISCUSSION_ID')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb b/spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb
index 6c6121c70e4..899074399a1 100644
--- a/spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb
+++ b/spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb
@@ -10,11 +10,12 @@ RSpec.describe UpdateImportSourcesOnApplicationSettings, feature_category: :migr
describe "#up" do
it 'removes google_code and preserves existing valid import sources' do
- settings.create!(import_sources: import_sources_with_google)
+ record = settings.create!(import_sources: import_sources_with_google.to_yaml)
migrate!
- expect(YAML.safe_load(ApplicationSetting.last.import_sources)).to eq(import_sources_without_google)
+ expect(record.reload.import_sources).to start_with('---')
+ expect(ApplicationSetting.last.import_sources).to eq(import_sources_without_google)
end
end
end
diff --git a/spec/migrations/20221209110935_fix_update_import_sources_on_application_settings_spec.rb b/spec/migrations/20221209110935_fix_update_import_sources_on_application_settings_spec.rb
new file mode 100644
index 00000000000..e5b20b2d48a
--- /dev/null
+++ b/spec/migrations/20221209110935_fix_update_import_sources_on_application_settings_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe FixUpdateImportSourcesOnApplicationSettings, feature_category: :migration do
+ let(:settings) { table(:application_settings) }
+ let(:import_sources) { %w[github git bitbucket bitbucket_server] }
+
+ describe "#up" do
+ shared_examples 'fixes import_sources on application_settings' do
+ it 'ensures YAML is stored' do
+ record = settings.create!(import_sources: data)
+
+ migrate!
+
+ expect(record.reload.import_sources).to start_with('---')
+ expect(ApplicationSetting.last.import_sources).to eq(import_sources)
+ end
+ end
+
+ context 'when import_sources is a String' do
+ let(:data) { import_sources.to_s }
+
+ it_behaves_like 'fixes import_sources on application_settings'
+ end
+
+ context 'when import_sources is already YAML' do
+ let(:data) { import_sources.to_yaml }
+
+ it_behaves_like 'fixes import_sources on application_settings'
+ end
+ end
+end
diff --git a/spec/support/helpers/features/branches_helpers.rb b/spec/support/helpers/features/branches_helpers.rb
index 2a50b41cb4e..d4f96718cc0 100644
--- a/spec/support/helpers/features/branches_helpers.rb
+++ b/spec/support/helpers/features/branches_helpers.rb
@@ -22,10 +22,14 @@ module Spec
end
def select_branch(branch_name)
- find(".js-branch-select").click
+ ref_selector = '.ref-selector'
+ find(ref_selector).click
+ wait_for_requests
- page.within("#new-branch-form .dropdown-menu") do
- click_link(branch_name)
+ page.within(ref_selector) do
+ fill_in _('Search by Git revision'), with: branch_name
+ wait_for_requests
+ find('li', text: branch_name, match: :prefer_exact).click
end
end
end
diff --git a/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb
index 15bc55c1526..c92741e8f10 100644
--- a/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe Gitlab::GithubImport::ImportDiffNoteWorker do
hash = {
'noteable_id' => 42,
'github_id' => 42,
+ 'html_url' => 'https://github.com/foo/bar/pull/42',
'path' => 'README.md',
'commit_id' => '123abc',
'diff_hunk' => "@@ -1 +1 @@\n-Hello\n+Hello world",