summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-09 21:09:19 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-09 21:09:19 +0000
commit254ec28f5448f6f353cd98f637985de3d1405854 (patch)
tree1c84ed7b7dd32db96454af034cd6c7e90699e76d /spec
parent141902c04943d5fb43c014b8cf42af60a3bc0cdf (diff)
downloadgitlab-ce-254ec28f5448f6f353cd98f637985de3d1405854.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb48
-rw-r--r--spec/frontend/diffs/components/app_spec.js6
-rw-r--r--spec/frontend/diffs/components/compare_dropdown_layout_spec.js91
-rw-r--r--spec/frontend/diffs/components/compare_versions_dropdown_spec.js179
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js25
-rw-r--r--spec/frontend/diffs/store/getters_versions_dropdowns_spec.js100
-rw-r--r--spec/frontend/notes/components/note_header_spec.js35
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb2
-rw-r--r--spec/services/search_service_spec.rb160
-rw-r--r--spec/tasks/gitlab/praefect_rake_spec.rb52
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