diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 00:09:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 00:09:19 +0300 |
commit | 254ec28f5448f6f353cd98f637985de3d1405854 (patch) | |
tree | 1c84ed7b7dd32db96454af034cd6c7e90699e76d /spec | |
parent | 141902c04943d5fb43c014b8cf42af60a3bc0cdf (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
10 files changed, 422 insertions, 276 deletions
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index d9345cfaced..9d243bf5a7f 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -789,25 +789,49 @@ describe Projects::PipelinesController do end end - context 'when test_report contains attachment and scope is with_attachment as a URL param' do - let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) } + context 'when junit_pipeline_screenshots_view is enabled' do + before do + stub_feature_flags(junit_pipeline_screenshots_view: { enabled: true, thing: project }) + end - it 'returns a test reports with attachment' do - get_test_report_json(scope: 'with_attachment') + context 'when test_report contains attachment and scope is with_attachment as a URL param' do + let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) } - expect(response).to have_gitlab_http_status(:ok) - expect(json_response["test_suites"]).to be_present + it 'returns a test reports with attachment' do + get_test_report_json(scope: 'with_attachment') + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response["test_suites"]).to be_present + expect(json_response["test_suites"].first["test_cases"].first).to include("attachment_url") + end + end + + context 'when test_report does not contain attachment and scope is with_attachment as a URL param' do + let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) } + + it 'returns a test reports with empty values' do + get_test_report_json(scope: 'with_attachment') + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response["test_suites"]).to be_empty + end end end - context 'when test_report does not contain attachment and scope is with_attachment as a URL param' do - let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) } + context 'when junit_pipeline_screenshots_view is disabled' do + before do + stub_feature_flags(junit_pipeline_screenshots_view: { enabled: false, thing: project }) + end - it 'returns a test reports with empty values' do - get_test_report_json(scope: 'with_attachment') + context 'when test_report contains attachment and scope is with_attachment as a URL param' do + let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) } - expect(response).to have_gitlab_http_status(:ok) - expect(json_response["test_suites"]).to be_empty + it 'returns a test reports without attachment_url' do + get_test_report_json(scope: 'with_attachment') + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response["test_suites"].first["test_cases"].first).not_to include("attachment_url") + end end end end diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 78e3ff4a60c..3a0354205f8 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -613,13 +613,7 @@ describe('diffs/components/app', () => { expect(wrapper.contains(CompareVersions)).toBe(true); expect(wrapper.find(CompareVersions).props()).toEqual( expect.objectContaining({ - targetBranch: { - branchName: 'target-branch', - versionIndex: -1, - path: '', - }, mergeRequestDiffs: diffsMockData, - mergeRequestDiff, }), ); }); diff --git a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js new file mode 100644 index 00000000000..a163a43daf1 --- /dev/null +++ b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js @@ -0,0 +1,91 @@ +import { shallowMount } from '@vue/test-utils'; +import { trimText } from 'helpers/text_helper'; +import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; +import CompareDropdownLayout from '~/diffs/components/compare_dropdown_layout.vue'; + +const TEST_COMMIT_TEXT = '1 commit'; +const TEST_CREATED_AT = '2018-10-23T11:49:16.611Z'; + +describe('CompareDropdownLayout', () => { + let wrapper; + + const createVersion = ({ id, isHead, isBase, selected, commitsText, createdAt }) => ({ + id, + href: `version/${id}`, + versionName: `version ${id}`, + isHead, + isBase, + short_commit_sha: `abcdef${id}`, + commitsText, + created_at: createdAt, + selected, + }); + + const createComponent = (propsData = {}) => { + wrapper = shallowMount(CompareDropdownLayout, { + propsData: { + ...propsData, + }, + }); + }; + + const findListItems = () => wrapper.findAll('li'); + const findListItemsData = () => + findListItems().wrappers.map(listItem => ({ + href: listItem.find('a').attributes('href'), + text: trimText(listItem.text()), + createdAt: listItem.findAll(TimeAgo).wrappers[0]?.props('time'), + isActive: listItem.find('a.is-active').exists(), + })); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('with versions', () => { + beforeEach(() => { + const versions = [ + createVersion({ + id: 1, + isHead: false, + isBase: true, + selected: true, + commitsText: TEST_COMMIT_TEXT, + createdAt: TEST_CREATED_AT, + }), + createVersion({ id: 2, isHead: true, isBase: false, selected: false }), + createVersion({ id: 3, isHead: false, isBase: false, selected: false }), + ]; + + createComponent({ versions }); + }); + + it('renders the selected version name', () => { + expect(wrapper.text()).toContain('version 1'); + }); + + it('renders versions in order', () => { + expect(findListItemsData()).toEqual([ + { + href: 'version/1', + text: 'version 1 (base) abcdef1 1 commit', + createdAt: TEST_CREATED_AT, + isActive: true, + }, + { + href: 'version/2', + text: 'version 2 (HEAD) abcdef2', + createdAt: undefined, + isActive: false, + }, + { + href: 'version/3', + text: 'version 3 abcdef3', + createdAt: undefined, + isActive: false, + }, + ]); + }); + }); +}); diff --git a/spec/frontend/diffs/components/compare_versions_dropdown_spec.js b/spec/frontend/diffs/components/compare_versions_dropdown_spec.js deleted file mode 100644 index 5033bdd9044..00000000000 --- a/spec/frontend/diffs/components/compare_versions_dropdown_spec.js +++ /dev/null @@ -1,179 +0,0 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import CompareVersionsDropdown from '~/diffs/components/compare_versions_dropdown.vue'; -import diffsMockData from '../mock_data/merge_request_diffs'; -import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; -import { TEST_HOST } from 'helpers/test_constants'; - -const localVue = createLocalVue(); -const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 }; -const startVersion = { version_index: 4 }; -const mergeRequestVersion = { - version_path: '123', -}; -const baseVersionPath = '/gnuwget/wget2/-/merge_requests/6/diffs?diff_id=37'; - -describe('CompareVersionsDropdown', () => { - let wrapper; - - const findSelectedVersion = () => wrapper.find('.dropdown-menu-toggle'); - const findVersionsListElements = () => wrapper.findAll('li'); - const findLinkElement = index => - findVersionsListElements() - .at(index) - .find('a'); - const findLastLink = () => findLinkElement(findVersionsListElements().length - 1); - - const createComponent = (props = {}) => { - wrapper = shallowMount(localVue.extend(CompareVersionsDropdown), { - localVue, - propsData: { ...props }, - }); - }; - - afterEach(() => { - wrapper.destroy(); - }); - - describe('selected version name', () => { - it('shows latest version when latest is selected', () => { - createComponent({ - mergeRequestVersion, - startVersion, - otherVersions: diffsMockData, - }); - - expect(findSelectedVersion().text()).toBe('latest version'); - }); - - it('shows target branch name for base branch', () => { - createComponent({ - targetBranch, - }); - - expect(findSelectedVersion().text()).toBe('tmp-wine-dev'); - }); - - it('shows correct version for non-base and non-latest branches', () => { - createComponent({ - startVersion, - targetBranch, - }); - - expect(findSelectedVersion().text()).toBe(`version ${startVersion.version_index}`); - }); - }); - - describe('target versions list', () => { - it('should have the same length as otherVersions if merge request version is present', () => { - createComponent({ - mergeRequestVersion, - otherVersions: diffsMockData, - }); - - expect(findVersionsListElements().length).toEqual(diffsMockData.length); - }); - - it('should have an otherVersions length plus 1 if no merge request version is present', () => { - createComponent({ - targetBranch, - otherVersions: diffsMockData, - }); - - expect(findVersionsListElements().length).toEqual(diffsMockData.length + 1); - }); - - it('should have base branch link as active on base branch', () => { - createComponent({ - targetBranch, - otherVersions: diffsMockData, - }); - - expect(findLastLink().classes()).toContain('is-active'); - }); - - it('should have correct branch link as active if start version present', () => { - createComponent({ - targetBranch, - startVersion, - otherVersions: diffsMockData, - }); - - expect(findLinkElement(0).classes()).toContain('is-active'); - }); - - it('should render a correct base version link', () => { - createComponent({ - baseVersionPath, - otherVersions: diffsMockData.slice(1), - targetBranch, - }); - - expect(findLastLink().attributes('href')).toEqual(baseVersionPath); - expect(findLastLink().text()).toContain('(base)'); - expect(findLastLink().text()).not.toContain('(HEAD)'); - }); - - it('should render a correct head version link', () => { - Object.defineProperty(window, 'location', { - writable: true, - value: { href: `${TEST_HOST}?diff_head=true` }, - }); - - createComponent({ - baseVersionPath, - otherVersions: diffsMockData.slice(1), - targetBranch, - }); - - expect(findLastLink().attributes('href')).toEqual(baseVersionPath); - expect(findLastLink().text()).not.toContain('(base)'); - expect(findLastLink().text()).toContain('(HEAD)'); - }); - - it('should not render commits count if no showCommitsCount is passed', () => { - createComponent({ - otherVersions: diffsMockData, - targetBranch, - }); - - const commitsCount = diffsMockData[0].commits_count; - - expect(findLinkElement(0).text()).not.toContain(`${commitsCount} commit`); - }); - - it('should render correct commits count if showCommitsCount is passed', () => { - createComponent({ - otherVersions: diffsMockData, - targetBranch, - showCommitCount: true, - }); - - const commitsCount = diffsMockData[0].commits_count; - - expect(findLinkElement(0).text()).toContain(`${commitsCount} commit`); - }); - - it('should render correct commit sha', () => { - createComponent({ - otherVersions: diffsMockData, - targetBranch, - }); - - const commitShaElement = findLinkElement(0).find('.commit-sha'); - - expect(commitShaElement.text()).toBe(diffsMockData[0].short_commit_sha); - }); - - it('should render correct time-ago ', () => { - createComponent({ - otherVersions: diffsMockData, - targetBranch, - }); - - const timeAgoElement = findLinkElement(0).find(TimeAgo); - - expect(timeAgoElement.exists()).toBe(true); - expect(timeAgoElement.props('time')).toBe(diffsMockData[0].created_at); - }); - }); -}); diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js index ff92a12eaf6..7f69a6344c1 100644 --- a/spec/frontend/diffs/components/compare_versions_spec.js +++ b/spec/frontend/diffs/components/compare_versions_spec.js @@ -12,23 +12,25 @@ localVue.use(Vuex); describe('CompareVersions', () => { let wrapper; - const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 }; + const targetBranchName = 'tmp-wine-dev'; const createWrapper = props => { const store = createStore(); + const mergeRequestDiff = diffsMockData[0]; store.state.diffs.addedLines = 10; store.state.diffs.removedLines = 20; store.state.diffs.diffFiles.push('test'); + store.state.diffs.targetBranchName = targetBranchName; + store.state.diffs.mergeRequestDiff = mergeRequestDiff; + store.state.diffs.mergeRequestDiffs = diffsMockData; wrapper = mount(CompareVersionsComponent, { localVue, store, propsData: { mergeRequestDiffs: diffsMockData, - mergeRequestDiff: diffsMockData[0], diffFilesLength: 0, - targetBranch, ...props, }, }); @@ -59,7 +61,7 @@ describe('CompareVersions', () => { expect(sourceDropdown.exists()).toBe(true); expect(targetDropdown.exists()).toBe(true); expect(sourceDropdown.find('a span').html()).toContain('latest version'); - expect(targetDropdown.find('a span').html()).toContain(targetBranch.branchName); + expect(targetDropdown.find('a span').html()).toContain(targetBranchName); }); it('should not render comparison dropdowns if no mergeRequestDiffs are specified', () => { @@ -119,21 +121,6 @@ describe('CompareVersions', () => { }); }); - describe('comparableDiffs', () => { - it('should not contain the first item in the mergeRequestDiffs property', () => { - const { comparableDiffs } = wrapper.vm; - const comparableDiffsMock = diffsMockData.slice(1); - - expect(comparableDiffs).toEqual(comparableDiffsMock); - }); - }); - - describe('baseVersionPath', () => { - it('should be set correctly from mergeRequestDiff', () => { - expect(wrapper.vm.baseVersionPath).toEqual(wrapper.vm.mergeRequestDiff.base_version_path); - }); - }); - describe('commit', () => { beforeEach(done => { wrapper.vm.$store.state.diffs.commit = getDiffWithCommit().commit; diff --git a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js new file mode 100644 index 00000000000..3e5ba66d5e4 --- /dev/null +++ b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js @@ -0,0 +1,100 @@ +import * as getters from '~/diffs/store/getters'; +import state from '~/diffs/store/modules/diff_state'; +import { DIFF_COMPARE_BASE_VERSION_INDEX } from '~/diffs/constants'; +import diffsMockData from '../mock_data/merge_request_diffs'; + +describe('Compare diff version dropdowns', () => { + let localState; + + beforeEach(() => { + localState = state(); + localState.mergeRequestDiff = { + base_version_path: 'basePath', + head_version_path: 'headPath', + version_index: 1, + }; + localState.targetBranchName = 'baseVersion'; + localState.mergeRequestDiffs = diffsMockData; + }); + + describe('selectedTargetIndex', () => { + it('without startVersion', () => { + expect(getters.selectedTargetIndex(localState)).toEqual(DIFF_COMPARE_BASE_VERSION_INDEX); + }); + + it('with startVersion', () => { + const startVersion = { version_index: 1 }; + localState.startVersion = startVersion; + expect(getters.selectedTargetIndex(localState)).toEqual(startVersion.version_index); + }); + }); + + it('selectedSourceIndex', () => { + expect(getters.selectedSourceIndex(localState)).toEqual( + localState.mergeRequestDiff.version_index, + ); + }); + + describe('diffCompareDropdownTargetVersions', () => { + // diffCompareDropdownTargetVersions slices the array at the first position + // and appends a "base" version which is why we use diffsMockData[1] below + // This is to display "base" at the end of the target dropdown + const expectedFirstVersion = { + ...diffsMockData[1], + href: expect.any(String), + versionName: expect.any(String), + }; + + const expectedBaseVersion = { + versionName: 'baseVersion', + version_index: DIFF_COMPARE_BASE_VERSION_INDEX, + href: 'basePath', + isBase: true, + }; + + it('base version selected', () => { + expectedFirstVersion.selected = false; + expectedBaseVersion.selected = true; + + const targetVersions = getters.diffCompareDropdownTargetVersions(localState, { + selectedTargetIndex: DIFF_COMPARE_BASE_VERSION_INDEX, + }); + + const lastVersion = targetVersions[targetVersions.length - 1]; + expect(targetVersions[0]).toEqual(expectedFirstVersion); + expect(lastVersion).toEqual(expectedBaseVersion); + }); + + it('first version selected', () => { + expectedFirstVersion.selected = true; + expectedBaseVersion.selected = false; + + localState.startVersion = expectedFirstVersion; + + const targetVersions = getters.diffCompareDropdownTargetVersions(localState, { + selectedTargetIndex: expectedFirstVersion.version_index, + }); + + const lastVersion = targetVersions[targetVersions.length - 1]; + expect(targetVersions[0]).toEqual(expectedFirstVersion); + expect(lastVersion).toEqual(expectedBaseVersion); + }); + }); + + it('diffCompareDropdownSourceVersions', () => { + const firstDiff = localState.mergeRequestDiffs[0]; + const expectedShape = { + ...firstDiff, + href: firstDiff.version_path, + commitsText: `${firstDiff.commits_count} commits,`, + versionName: 'latest version', + selected: true, + }; + + const sourceVersions = getters.diffCompareDropdownSourceVersions(localState, { + selectedSourceIndex: expectedShape.version_index, + }); + expect(sourceVersions[0]).toEqual(expectedShape); + expect(sourceVersions[1].selected).toBe(false); + }); +}); diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js index 6544ad3e1fe..642ab5138dc 100644 --- a/spec/frontend/notes/components/note_header_spec.js +++ b/spec/frontend/notes/components/note_header_spec.js @@ -1,6 +1,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; import NoteHeader from '~/notes/components/note_header.vue'; +import GitlabTeamMemberBadge from '~/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'; const localVue = createLocalVue(); localVue.use(Vuex); @@ -17,6 +18,15 @@ describe('NoteHeader component', () => { const findActionText = () => wrapper.find({ ref: 'actionText' }); const findTimestamp = () => wrapper.find({ ref: 'noteTimestamp' }); + const author = { + avatar_url: null, + id: 1, + name: 'Root', + path: '/root', + state: 'active', + username: 'root', + }; + const createComponent = props => { wrapper = shallowMount(NoteHeader, { localVue, @@ -83,16 +93,7 @@ describe('NoteHeader component', () => { }); it('renders an author link if author is passed to props', () => { - createComponent({ - author: { - avatar_url: null, - id: 1, - name: 'Root', - path: '/root', - state: 'active', - username: 'root', - }, - }); + createComponent({ author }); expect(wrapper.find('.js-user-link').exists()).toBe(true); }); @@ -138,4 +139,18 @@ describe('NoteHeader component', () => { expect(actions.setTargetNoteHash).toHaveBeenCalled(); }); }); + + test.each` + props | expected | message1 | message2 + ${{ author: { ...author, is_gitlab_employee: true } }} | ${true} | ${'renders'} | ${'true'} + ${{ author: { ...author, is_gitlab_employee: false } }} | ${false} | ${"doesn't render"} | ${'false'} + ${{ author }} | ${false} | ${"doesn't render"} | ${'undefined'} + `( + '$message1 GitLab team member badge when `is_gitlab_employee` is $message2', + ({ props, expected }) => { + createComponent(props); + + expect(wrapper.find(GitlabTeamMemberBadge).exists()).toBe(expected); + }, + ); }); diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb index 9fc0fdeb1bc..1eac580bc5e 100644 --- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb @@ -6,7 +6,7 @@ def match_mr1_note(content_regex) MergeRequest.find_by(title: 'MR1').notes.select { |n| n.note.match(/#{content_regex}/)}.first end -describe Gitlab::ImportExport::Project::TreeRestorer do +describe Gitlab::ImportExport::Project::TreeRestorer, quarantine: { flaky: 'https://gitlab.com/gitlab-org/gitlab/-/issues/213793' } do include ImportExport::CommonUtil let(:shared) { project.import_export_shared } diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb index 10dafaebe85..97d7ca6e1ad 100644 --- a/spec/services/search_service_spec.rb +++ b/spec/services/search_service_spec.rb @@ -3,16 +3,16 @@ require 'spec_helper' describe SearchService do - let(:user) { create(:user) } + let_it_be(:user) { create(:user) } - let(:accessible_group) { create(:group, :private) } - let(:inaccessible_group) { create(:group, :private) } - let!(:group_member) { create(:group_member, group: accessible_group, user: user) } + let_it_be(:accessible_group) { create(:group, :private) } + let_it_be(:inaccessible_group) { create(:group, :private) } + let_it_be(:group_member) { create(:group_member, group: accessible_group, user: user) } - let!(:accessible_project) { create(:project, :private, name: 'accessible_project') } - let(:note) { create(:note_on_issue, project: accessible_project) } + let_it_be(:accessible_project) { create(:project, :repository, :private, name: 'accessible_project') } + let_it_be(:note) { create(:note_on_issue, project: accessible_project) } - let!(:inaccessible_project) { create(:project, :private, name: 'inaccessible_project') } + let_it_be(:inaccessible_project) { create(:project, :repository, :private, name: 'inaccessible_project') } let(:snippet) { create(:snippet, author: user) } let(:group_project) { create(:project, group: accessible_group, name: 'group_project') } @@ -298,67 +298,129 @@ describe SearchService do end context 'redacting search results' do - shared_examples 'it redacts incorrect results' do - before do - allow(Ability).to receive(:allowed?).and_return(allowed) - end + let(:search) { 'anything' } - context 'when allowed' do - let(:allowed) { true } + subject(:result) { search_service.search_objects } - it 'does nothing' do - expect(results).not_to be_empty - expect(results).to all(be_an(model_class)) - end - end + def found_blob(project) + Gitlab::Search::FoundBlob.new(project: project) + end - context 'when disallowed' do - let(:allowed) { false } + def found_wiki_page(project) + Gitlab::Search::FoundWikiPage.new(found_blob(project)) + end - it 'does nothing' do - expect(results).to be_empty - end - end + before do + expect(search_service) + .to receive(:search_results) + .and_return(double('search results', objects: unredacted_results)) + end + + def ar_relation(klass, *objects) + klass.id_in(objects.map(&:id)) + end + + def kaminari_array(*objects) + Kaminari.paginate_array(objects).page(1).per(20) end context 'issues' do - let(:issue) { create(:issue, project: accessible_project) } + let(:readable) { create(:issue, project: accessible_project) } + let(:unreadable) { create(:issue, project: inaccessible_project) } + let(:unredacted_results) { ar_relation(Issue, readable, unreadable) } let(:scope) { 'issues' } - let(:model_class) { Issue } - let(:ability) { :read_issue } - let(:search) { issue.title } - let(:results) { subject.search_objects } - it_behaves_like 'it redacts incorrect results' + it 'redacts the inaccessible issue' do + expect(result).to contain_exactly(readable) + end end context 'notes' do - let(:note) { create(:note_on_commit, project: accessible_project) } + let(:readable) { create(:note_on_commit, project: accessible_project) } + let(:unreadable) { create(:note_on_commit, project: inaccessible_project) } + let(:unredacted_results) { ar_relation(Note, readable, unreadable) } let(:scope) { 'notes' } - let(:model_class) { Note } - let(:ability) { :read_note } - let(:search) { note.note } - let(:results) do - described_class.new( - user, - project_id: accessible_project.id, - scope: scope, - search: note.note - ).search_objects - end - it_behaves_like 'it redacts incorrect results' + it 'redacts the inaccessible note' do + expect(result).to contain_exactly(readable) + end end context 'merge_requests' do + let(:readable) { create(:merge_request, source_project: accessible_project, author: user) } + let(:unreadable) { create(:merge_request, source_project: inaccessible_project) } + let(:unredacted_results) { ar_relation(MergeRequest, readable, unreadable) } let(:scope) { 'merge_requests' } - let(:model_class) { MergeRequest } - let(:ability) { :read_merge_request } - let(:merge_request) { create(:merge_request, source_project: accessible_project, author: user) } - let(:search) { merge_request.title } - let(:results) { subject.search_objects } - it_behaves_like 'it redacts incorrect results' + it 'redacts the inaccessible merge request' do + expect(result).to contain_exactly(readable) + end + end + + context 'project repository blobs' do + let(:readable) { found_blob(accessible_project) } + let(:unreadable) { found_blob(inaccessible_project) } + let(:unredacted_results) { kaminari_array(readable, unreadable) } + let(:scope) { 'blobs' } + + it 'redacts the inaccessible blob' do + expect(result).to contain_exactly(readable) + end + end + + context 'project wiki blobs' do + let(:readable) { found_wiki_page(accessible_project) } + let(:unreadable) { found_wiki_page(inaccessible_project) } + let(:unredacted_results) { kaminari_array(readable, unreadable) } + let(:scope) { 'wiki_blobs' } + + it 'redacts the inaccessible blob' do + expect(result).to contain_exactly(readable) + end + end + + context 'project snippets' do + let(:readable) { create(:project_snippet, project: accessible_project) } + let(:unreadable) { create(:project_snippet, project: inaccessible_project) } + let(:unredacted_results) { ar_relation(ProjectSnippet, readable, unreadable) } + let(:scope) { 'snippet_blobs' } + + it 'redacts the inaccessible snippet' do + expect(result).to contain_exactly(readable) + end + end + + context 'personal snippets' do + let(:readable) { create(:personal_snippet, :private, author: user) } + let(:unreadable) { create(:personal_snippet, :private) } + let(:unredacted_results) { ar_relation(PersonalSnippet, readable, unreadable) } + let(:scope) { 'snippet_blobs' } + + it 'redacts the inaccessible snippet' do + expect(result).to contain_exactly(readable) + end + end + + context 'commits' do + let(:readable) { accessible_project.commit } + let(:unreadable) { inaccessible_project.commit } + let(:unredacted_results) { kaminari_array(readable, unreadable) } + let(:scope) { 'commits' } + + it 'redacts the inaccessible commit' do + expect(result).to contain_exactly(readable) + end + end + + context 'users' do + let(:other_user) { create(:user) } + let(:unredacted_results) { ar_relation(User, user, other_user) } + let(:scope) { 'users' } + + it 'passes the users through' do + # Users are always visible to everyone + expect(result).to contain_exactly(user, other_user) + end end end end diff --git a/spec/tasks/gitlab/praefect_rake_spec.rb b/spec/tasks/gitlab/praefect_rake_spec.rb new file mode 100644 index 00000000000..d986a778c8c --- /dev/null +++ b/spec/tasks/gitlab/praefect_rake_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'rake_helper' + +describe 'gitlab:praefect:replicas' do + before do + Rake.application.rake_require 'tasks/gitlab/praefect' + end + + let(:project) { create(:project, :repository) } + let(:repository) { project.repository } + + describe 'replicas', :praefect do + context 'when a valid project id is used as the argument' do + let(:project_arg) { project.id } + + it "calls praefect info service's replicas method" do + expect_any_instance_of(Gitlab::GitalyClient::PraefectInfoService).to receive(:replicas).and_call_original + + run_rake_task('gitlab:praefect:replicas', project_arg) + end + + it 'prints out the expected row' do + row = /#{project.name}\s+\| #{project.repository.checksum}/ + + expect { run_rake_task('gitlab:praefect:replicas', project_arg) }.to output(row).to_stdout + end + end + + context 'when a non existent project id is used as the argument' do + let(:project_arg) { '2' } + + it "does not call praefect info service's replicas method" do + expect_any_instance_of(Gitlab::GitalyClient::PraefectInfoService).not_to receive(:replicas) + + run_rake_task('gitlab:praefect:replicas', project_arg) + end + end + + context 'when replicas throws an exception' do + before do + allow_next_instance_of(Gitlab::GitalyClient::PraefectInfoService) do |instance| + expect(instance).to receive(:replicas).and_raise("error") + end + end + + it 'aborts with the correct error message' do + expect { run_rake_task('gitlab:praefect:replicas', project.id) }.to output("Something went wrong when getting replicas.\n").to_stdout + end + end + end +end |