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-03-24 15:09:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-24 15:09:42 +0300
commit729e3765d5feb762df1ccfbc228a8dd4662aa3f9 (patch)
treef326420fc64999c6bcc28816ed54f0972fb46459 /spec
parent6f7881ee9dcec34141a8f34fc814b56b366d2b48 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/releases/evidences_controller_spec.rb165
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb145
-rw-r--r--spec/factories/events.rb4
-rw-r--r--spec/factories/evidences.rb2
-rw-r--r--spec/finders/events_finder_spec.rb30
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release/evidence.json14
-rw-r--r--spec/frontend/locale/index_spec.js (renamed from spec/javascripts/locale/index_spec.js)12
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js59
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js46
-rw-r--r--spec/frontend/releases/components/evidence_block_spec.js15
-rw-r--r--spec/frontend/releases/mock_data.js23
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb35
-rw-r--r--spec/helpers/nav_helper_spec.rb20
-rw-r--r--spec/lib/api/entities/release_spec.rb34
-rw-r--r--spec/lib/event_filter_spec.rb50
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/models/event_collection_spec.rb81
-rw-r--r--spec/models/event_spec.rb21
-rw-r--r--spec/models/release_spec.rb10
-rw-r--r--spec/models/releases/evidence_spec.rb (renamed from spec/models/evidence_spec.rb)2
-rw-r--r--spec/presenters/release_presenter_spec.rb24
-rw-r--r--spec/requests/api/events_spec.rb20
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb3
-rw-r--r--spec/requests/api/groups_spec.rb22
-rw-r--r--spec/requests/api/releases_spec.rb21
-rw-r--r--spec/services/event_create_service_spec.rb40
-rw-r--r--spec/services/wiki_pages/base_service_spec.rb20
-rw-r--r--spec/services/wiki_pages/create_service_spec.rb49
-rw-r--r--spec/services/wiki_pages/destroy_service_spec.rb22
-rw-r--r--spec/services/wiki_pages/update_service_spec.rb52
-rw-r--r--spec/support/helpers/stub_experiments.rb4
-rw-r--r--spec/workers/create_evidence_worker_spec.rb4
34 files changed, 784 insertions, 273 deletions
diff --git a/spec/controllers/projects/releases/evidences_controller_spec.rb b/spec/controllers/projects/releases/evidences_controller_spec.rb
new file mode 100644
index 00000000000..d3808087681
--- /dev/null
+++ b/spec/controllers/projects/releases/evidences_controller_spec.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::Releases::EvidencesController do
+ let!(:project) { create(:project, :repository, :public) }
+ let_it_be(:private_project) { create(:project, :repository, :private) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let(:user) { developer }
+
+ before do
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ end
+
+ shared_examples_for 'successful request' do
+ it 'renders a 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
+ shared_examples_for 'not found' do
+ it 'renders 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ describe 'GET #show' do
+ let_it_be(:tag_name) { "v1.1.0-evidence" }
+ let!(:release) { create(:release, :with_evidence, project: project, tag: tag_name) }
+ let(:evidence) { release.evidences.first }
+ let(:tag) { CGI.escape(release.tag) }
+ let(:format) { :json }
+
+ subject do
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ tag: tag,
+ id: evidence.id,
+ format: format
+ }
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when the user is a developer' do
+ it 'returns the correct evidence summary as a json' do
+ subject
+
+ expect(json_response).to eq(evidence.summary)
+ end
+
+ context 'when the release was created before evidence existed' do
+ before do
+ evidence.destroy
+ end
+
+ it_behaves_like 'not found'
+ end
+ end
+
+ context 'when the user is a guest for the project' do
+ before do
+ project.add_guest(user)
+ end
+
+ context 'when the project is private' do
+ let(:project) { private_project }
+
+ it_behaves_like 'not found'
+ end
+
+ context 'when the project is public' do
+ it_behaves_like 'successful request'
+ end
+ end
+
+ context 'when release is associated to a milestone which includes an issue' do
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:milestone) { create(:milestone, project: project, issues: [issue]) }
+ let_it_be(:release) { create(:release, project: project, tag: tag_name, milestones: [milestone]) }
+
+ before do
+ create(:evidence, release: release)
+ end
+
+ shared_examples_for 'does not show the issue in evidence' do
+ it do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['release']['milestones']
+ .all? { |milestone| milestone['issues'].nil? }).to eq(true)
+ end
+ end
+
+ shared_examples_for 'evidence not found' do
+ it do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ shared_examples_for 'safely expose evidence' do
+ it_behaves_like 'does not show the issue in evidence'
+
+ context 'when the issue is confidential' do
+ let(:issue) { create(:issue, :confidential, project: project) }
+
+ it_behaves_like 'does not show the issue in evidence'
+ end
+
+ context 'when the user is the author of the confidential issue' do
+ let(:issue) { create(:issue, :confidential, project: project, author: user) }
+
+ it_behaves_like 'does not show the issue in evidence'
+ end
+
+ context 'when project is private' do
+ let!(:project) { create(:project, :repository, :private) }
+
+ it_behaves_like 'evidence not found'
+ end
+
+ context 'when project restricts the visibility of issues to project members only' do
+ let!(:project) { create(:project, :repository, :issues_private) }
+
+ it_behaves_like 'evidence not found'
+ end
+ end
+
+ context 'when user is non-project member' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'safely expose evidence'
+ end
+
+ context 'when user is auditor', if: Gitlab.ee? do
+ let(:user) { create(:user, :auditor) }
+
+ it_behaves_like 'safely expose evidence'
+ end
+
+ context 'when external authorization control is enabled' do
+ let(:user) { create(:user) }
+
+ before do
+ stub_application_setting(external_authorization_service_enabled: true)
+ end
+
+ it_behaves_like 'evidence not found'
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index ca073c520cd..4c957e22d24 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
describe Projects::ReleasesController do
- let!(:project) { create(:project, :repository, :public) }
- let!(:private_project) { create(:project, :repository, :private) }
- let(:user) { developer }
- let(:developer) { create(:user) }
- let(:reporter) { create(:user) }
+ let!(:project) { create(:project, :repository, :public) }
+ let_it_be(:private_project) { create(:project, :repository, :private) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:user) { developer }
let!(:release_1) { create(:release, project: project, released_at: Time.zone.parse('2018-10-18')) }
let!(:release_2) { create(:release, project: project, released_at: Time.zone.parse('2019-10-19')) }
@@ -295,141 +295,6 @@ describe Projects::ReleasesController do
end
end
- describe 'GET #evidence' do
- let_it_be(:tag_name) { "v1.1.0-evidence" }
- let!(:release) { create(:release, :with_evidence, project: project, tag: tag_name) }
- let(:tag) { CGI.escape(release.tag) }
- let(:format) { :json }
-
- subject do
- get :evidence, params: {
- namespace_id: project.namespace,
- project_id: project,
- tag: tag,
- format: format
- }
- end
-
- before do
- sign_in(user)
- end
-
- context 'when the user is a developer' do
- it 'returns the correct evidence summary as a json' do
- subject
-
- expect(json_response).to eq(release.evidence.summary)
- end
-
- context 'when the release was created before evidence existed' do
- before do
- release.evidence.destroy
- end
-
- it 'returns an empty json' do
- subject
-
- expect(json_response).to eq({})
- end
- end
- end
-
- context 'when the user is a guest for the project' do
- before do
- project.add_guest(user)
- end
-
- context 'when the project is private' do
- let(:project) { private_project }
-
- it_behaves_like 'not found'
- end
-
- context 'when the project is public' do
- it_behaves_like 'successful request'
- end
- end
-
- context 'when release is associated to a milestone which includes an issue' do
- let_it_be(:project) { create(:project, :repository, :public) }
- let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:milestone) { create(:milestone, project: project, issues: [issue]) }
- let_it_be(:release) { create(:release, project: project, tag: tag_name, milestones: [milestone]) }
-
- before do
- create(:evidence, release: release)
- end
-
- shared_examples_for 'does not show the issue in evidence' do
- it do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['release']['milestones']
- .all? { |milestone| milestone['issues'].nil? }).to eq(true)
- end
- end
-
- shared_examples_for 'evidence not found' do
- it do
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- shared_examples_for 'safely expose evidence' do
- it_behaves_like 'does not show the issue in evidence'
-
- context 'when the issue is confidential' do
- let(:issue) { create(:issue, :confidential, project: project) }
-
- it_behaves_like 'does not show the issue in evidence'
- end
-
- context 'when the user is the author of the confidential issue' do
- let(:issue) { create(:issue, :confidential, project: project, author: user) }
-
- it_behaves_like 'does not show the issue in evidence'
- end
-
- context 'when project is private' do
- let!(:project) { create(:project, :repository, :private) }
-
- it_behaves_like 'evidence not found'
- end
-
- context 'when project restricts the visibility of issues to project members only' do
- let!(:project) { create(:project, :repository, :issues_private) }
-
- it_behaves_like 'evidence not found'
- end
- end
-
- context 'when user is non-project member' do
- let(:user) { create(:user) }
-
- it_behaves_like 'safely expose evidence'
- end
-
- context 'when user is auditor', if: Gitlab.ee? do
- let(:user) { create(:user, :auditor) }
-
- it_behaves_like 'safely expose evidence'
- end
-
- context 'when external authorization control is enabled' do
- let(:user) { create(:user) }
-
- before do
- stub_application_setting(external_authorization_service_enabled: true)
- end
-
- it_behaves_like 'evidence not found'
- end
- end
- end
-
private
def get_index
diff --git a/spec/factories/events.rb b/spec/factories/events.rb
index b4285627de3..5b456bb58ff 100644
--- a/spec/factories/events.rb
+++ b/spec/factories/events.rb
@@ -25,12 +25,12 @@ FactoryBot.define do
factory :wiki_page_event do
action { Event::CREATED }
+ project { @overrides[:wiki_page]&.project || create(:project, :wiki_repo) }
+ target { create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
transient do
wiki_page { create(:wiki_page, project: project) }
end
-
- target { create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
end
end
diff --git a/spec/factories/evidences.rb b/spec/factories/evidences.rb
index 964f232a1c9..77116d8e9ed 100644
--- a/spec/factories/evidences.rb
+++ b/spec/factories/evidences.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :evidence do
+ factory :evidence, class: 'Releases::Evidence' do
release
end
end
diff --git a/spec/finders/events_finder_spec.rb b/spec/finders/events_finder_spec.rb
index 5c28b31e8c8..443e9ab4bc4 100644
--- a/spec/finders/events_finder_spec.rb
+++ b/spec/finders/events_finder_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe EventsFinder do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
let(:other_user) { create(:user) }
let(:project1) { create(:project, :private, creator_id: user.id, namespace: user.namespace) }
@@ -20,7 +20,7 @@ describe EventsFinder do
let(:opened_merge_request3) { create(:merge_request, source_project: project1, author: other_user) }
let!(:other_developer_event) { create(:event, project: project1, author: other_user, target: opened_merge_request3, action: Event::CREATED) }
- let(:public_project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
+ let_it_be(:public_project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
let(:confidential_issue) { create(:closed_issue, confidential: true, project: public_project, author: user) }
let!(:confidential_event) { create(:event, project: public_project, author: user, target: confidential_issue, action: Event::CLOSED) }
@@ -59,6 +59,32 @@ describe EventsFinder do
end
end
+ describe 'wiki events feature flag' do
+ let_it_be(:events) { create_list(:wiki_page_event, 3, project: public_project) }
+
+ subject(:finder) { described_class.new(source: public_project, target_type: 'wiki', current_user: user) }
+
+ context 'the wiki_events feature flag is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'omits the wiki page events' do
+ expect(finder.execute).to be_empty
+ end
+ end
+
+ context 'the wiki_events feature flag is enabled' do
+ before do
+ stub_feature_flags(wiki_events: true)
+ end
+
+ it 'can find the wiki events' do
+ expect(finder.execute).to match_array(events)
+ end
+ end
+ end
+
context 'dashboard events' do
before do
project1.add_developer(other_user)
diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json
index a239be09919..02e23d2732d 100644
--- a/spec/fixtures/api/schemas/public_api/v4/release.json
+++ b/spec/fixtures/api/schemas/public_api/v4/release.json
@@ -22,6 +22,10 @@
"commit_path": { "type": "string" },
"tag_path": { "type": "string" },
"name": { "type": "string" },
+ "evidences": {
+ "type": "array",
+ "items": { "$ref": "release/evidence.json" }
+ },
"assets": {
"required": ["count", "links", "sources"],
"properties": {
diff --git a/spec/fixtures/api/schemas/public_api/v4/release/evidence.json b/spec/fixtures/api/schemas/public_api/v4/release/evidence.json
new file mode 100644
index 00000000000..fbebac0acaa
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/release/evidence.json
@@ -0,0 +1,14 @@
+{
+ "type": "object",
+ "required" : [
+ "sha",
+ "filepath",
+ "collected_at"
+ ],
+ "properties" : {
+ "sha": { "type": "string" },
+ "filepath": { "type": "string" },
+ "collected_at": { "type": "date" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/javascripts/locale/index_spec.js b/spec/frontend/locale/index_spec.js
index 29b0b21eed7..346ed5182f4 100644
--- a/spec/javascripts/locale/index_spec.js
+++ b/spec/frontend/locale/index_spec.js
@@ -1,11 +1,9 @@
import { createDateTimeFormat, languageCode } from '~/locale';
-import { setLanguage } from '../helpers/locale_helper';
+import { setLanguage } from 'helpers/locale_helper';
describe('locale', () => {
- afterEach(() => {
- setLanguage(null);
- });
+ afterEach(() => setLanguage(null));
describe('languageCode', () => {
it('parses the lang attribute', () => {
@@ -22,14 +20,12 @@ describe('locale', () => {
});
describe('createDateTimeFormat', () => {
- beforeEach(() => {
- setLanguage('de');
- });
+ beforeEach(() => setLanguage('en'));
it('creates an instance of Intl.DateTimeFormat', () => {
const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' });
- expect(dateFormat.format(new Date(2015, 6, 3))).toBe('3. Juli 2015');
+ expect(dateFormat.format(new Date(2015, 6, 3))).toBe('July 3, 2015');
});
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index c9375df07e8..77603c16f82 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -75,17 +75,66 @@ describe('DiscussionCounter component', () => {
});
it.each`
- title | resolved | hasNextBtn | isActive | icon | groupLength
- ${'hasNextButton'} | ${false} | ${true} | ${false} | ${'check-circle'} | ${2}
- ${'allResolved'} | ${true} | ${false} | ${true} | ${'check-circle-filled'} | ${0}
- `('renders correctly if $title', ({ resolved, hasNextBtn, isActive, icon, groupLength }) => {
+ title | resolved | isActive | icon | groupLength
+ ${'not allResolved'} | ${false} | ${false} | ${'check-circle'} | ${3}
+ ${'allResolved'} | ${true} | ${true} | ${'check-circle-filled'} | ${1}
+ `('renders correctly if $title', ({ resolved, isActive, icon, groupLength }) => {
updateStore({ resolvable: true, resolved });
wrapper = shallowMount(DiscussionCounter, { store, localVue });
- expect(wrapper.find(`.has-next-btn`).exists()).toBe(hasNextBtn);
expect(wrapper.find(`.is-active`).exists()).toBe(isActive);
expect(wrapper.find({ name: icon }).exists()).toBe(true);
expect(wrapper.findAll('[role="group"').length).toBe(groupLength);
});
});
+
+ describe('toggle all threads button', () => {
+ let toggleAllButton;
+ const updateStoreWithExpanded = expanded => {
+ const discussion = { ...discussionMock, expanded };
+ store.commit(types.SET_INITIAL_DISCUSSIONS, [discussion]);
+ store.dispatch('updateResolvableDiscussionsCounts');
+ wrapper = shallowMount(DiscussionCounter, { store, localVue });
+ toggleAllButton = wrapper.find('.toggle-all-discussions-btn');
+ };
+
+ afterEach(() => wrapper.destroy());
+
+ it('calls button handler when clicked', () => {
+ updateStoreWithExpanded(true);
+
+ wrapper.setMethods({ handleExpandDiscussions: jest.fn() });
+ toggleAllButton.trigger('click');
+
+ expect(wrapper.vm.handleExpandDiscussions).toHaveBeenCalledTimes(1);
+ });
+
+ it('collapses all discussions if expanded', () => {
+ updateStoreWithExpanded(true);
+
+ expect(wrapper.vm.allExpanded).toBe(true);
+ expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+
+ toggleAllButton.trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.allExpanded).toBe(false);
+ expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+ });
+ });
+
+ it('expands all discussions if collapsed', () => {
+ updateStoreWithExpanded(false);
+
+ expect(wrapper.vm.allExpanded).toBe(false);
+ expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+
+ toggleAllButton.trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.allExpanded).toBe(true);
+ expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+ });
+ });
+ });
});
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index ee772afbc03..ea5658821b1 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -329,6 +329,52 @@ describe('Notes Store mutations', () => {
});
});
+ describe('SET_EXPAND_DISCUSSIONS', () => {
+ it('should succeed when discussions are null', () => {
+ const state = {};
+
+ mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds: null, expanded: true });
+
+ expect(state).toEqual({});
+ });
+
+ it('should succeed when discussions are empty', () => {
+ const state = {};
+
+ mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds: [], expanded: true });
+
+ expect(state).toEqual({});
+ });
+
+ it('should open all closed discussions', () => {
+ const discussion1 = Object.assign({}, discussionMock, { id: 0, expanded: false });
+ const discussion2 = Object.assign({}, discussionMock, { id: 1, expanded: true });
+ const discussionIds = [discussion1.id, discussion2.id];
+
+ const state = { discussions: [discussion1, discussion2] };
+
+ mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: true });
+
+ state.discussions.forEach(discussion => {
+ expect(discussion.expanded).toEqual(true);
+ });
+ });
+
+ it('should close all opened discussions', () => {
+ const discussion1 = Object.assign({}, discussionMock, { id: 0, expanded: false });
+ const discussion2 = Object.assign({}, discussionMock, { id: 1, expanded: true });
+ const discussionIds = [discussion1.id, discussion2.id];
+
+ const state = { discussions: [discussion1, discussion2] };
+
+ mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: false });
+
+ state.discussions.forEach(discussion => {
+ expect(discussion.expanded).toEqual(false);
+ });
+ });
+ });
+
describe('UPDATE_NOTE', () => {
it('should update a note', () => {
const state = {
diff --git a/spec/frontend/releases/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js
index c76a0e04dce..ba60a79e464 100644
--- a/spec/frontend/releases/components/evidence_block_spec.js
+++ b/spec/frontend/releases/components/evidence_block_spec.js
@@ -1,7 +1,6 @@
import { mount } from '@vue/test-utils';
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlIcon } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import { release as originalRelease } from '../mock_data';
import EvidenceBlock from '~/releases/components/evidence_block.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -32,11 +31,11 @@ describe('Evidence Block', () => {
});
it('renders the evidence icon', () => {
- expect(wrapper.find(Icon).props('name')).toBe('review-list');
+ expect(wrapper.find(GlIcon).props('name')).toBe('review-list');
});
it('renders the title for the dowload link', () => {
- expect(wrapper.find(GlLink).text()).toBe(`${release.tagName}-evidence.json`);
+ expect(wrapper.find(GlLink).text()).toBe('v1.1.2-evidences-1.json');
});
it('renders the correct hover text for the download', () => {
@@ -44,19 +43,19 @@ describe('Evidence Block', () => {
});
it('renders the correct file link for download', () => {
- expect(wrapper.find(GlLink).attributes().download).toBe(`${release.tagName}-evidence.json`);
+ expect(wrapper.find(GlLink).attributes().download).toBe('v1.1.2-evidences-1.json');
});
describe('sha text', () => {
it('renders the short sha initially', () => {
- expect(wrapper.find('.js-short').text()).toBe(truncateSha(release.evidenceSha));
+ expect(wrapper.find('.js-short').text()).toBe(truncateSha(release.evidences[0].sha));
});
it('renders the long sha after expansion', () => {
wrapper.find('.js-text-expander-prepend').trigger('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.js-expanded').text()).toBe(release.evidenceSha);
+ expect(wrapper.find('.js-expanded').text()).toBe(release.evidences[0].sha);
});
});
});
@@ -72,7 +71,7 @@ describe('Evidence Block', () => {
it('copies the sha', () => {
expect(wrapper.find(ClipboardButton).attributes('data-clipboard-text')).toBe(
- release.evidenceSha,
+ release.evidences[0].sha,
);
});
});
diff --git a/spec/frontend/releases/mock_data.js b/spec/frontend/releases/mock_data.js
index 85e6bab71ba..bd5fc86275e 100644
--- a/spec/frontend/releases/mock_data.js
+++ b/spec/frontend/releases/mock_data.js
@@ -43,7 +43,6 @@ export const release = {
description_html: '<p data-sourcepos="1:1-1:21" dir="auto">A super nice release!</p>',
created_at: '2019-08-26T17:54:04.952Z',
released_at: '2019-08-26T17:54:04.807Z',
- evidence_sha: 'fb3a125fd69a0e5048ebfb0ba43eb32ce4911520dd8d',
author: {
id: 1,
name: 'Administrator',
@@ -69,10 +68,28 @@ export const release = {
commit_path: '/root/release-test/commit/c22b0728d1b465f82898c884d32b01aa642f96c1',
upcoming_release: false,
milestones,
+ evidences: [
+ {
+ filepath:
+ 'https://20592.qa-tunnel.gitlab.info/root/test-deployments/-/releases/v1.1.2/evidences/1.json',
+ sha: 'fb3a125fd69a0e5048ebfb0ba43eb32ce4911520dd8d',
+ collected_at: '2018-10-19 15:43:20 +0200',
+ },
+ {
+ filepath:
+ 'https://20592.qa-tunnel.gitlab.info/root/test-deployments/-/releases/v1.1.2/evidences/2.json',
+ sha: '6ebd17a66e6a861175735416e49cf677678029805712dd71bb805c609e2d9108',
+ collected_at: '2018-10-19 15:43:20 +0200',
+ },
+ {
+ filepath:
+ 'https://20592.qa-tunnel.gitlab.info/root/test-deployments/-/releases/v1.1.2/evidences/3.json',
+ sha: '2f65beaf275c3cb4b4e24fb01d481cc475d69c957830833f15338384816b5cba',
+ collected_at: '2018-10-19 15:43:20 +0200',
+ },
+ ],
assets: {
count: 5,
- evidence_file_path:
- 'https://20592.qa-tunnel.gitlab.info/root/test-deployments/-/releases/v1.1.2/evidence.json',
sources: [
{
format: 'zip',
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 7cfef9b4cc7..4467c228e96 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -7,15 +7,20 @@ describe Resolvers::IssuesResolver do
let(:current_user) { create(:user) }
- context "with a project" do
- let_it_be(:project) { create(:project) }
- let_it_be(:milestone) { create(:milestone, project: project) }
- let_it_be(:assignee) { create(:user) }
- let_it_be(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago, milestone: milestone) }
- let_it_be(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago, assignees: [assignee]) }
- let_it_be(:label1) { create(:label, project: project) }
- let_it_be(:label2) { create(:label, project: project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:other_project) { create(:project, group: group) }
+
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago, milestone: milestone) }
+ let_it_be(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago, assignees: [assignee]) }
+ let_it_be(:issue3) { create(:issue, project: other_project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago, assignees: [assignee]) }
+ let_it_be(:issue4) { create(:issue) }
+ let_it_be(:label1) { create(:label, project: project) }
+ let_it_be(:label2) { create(:label, project: project) }
+ context "with a project" do
before do
project.add_developer(current_user)
create(:label_link, label: label1, target: issue1)
@@ -184,6 +189,20 @@ describe Resolvers::IssuesResolver do
end
end
+ context "with a group" do
+ before do
+ group.add_developer(current_user)
+ end
+
+ describe '#resolve' do
+ it 'finds all group issues' do
+ result = resolve(described_class, obj: group, ctx: { current_user: current_user })
+
+ expect(result).to contain_exactly(issue1, issue2, issue3)
+ end
+ end
+ end
+
context "when passing a non existent, batch loaded project" do
let(:project) do
BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb
index f92dca11136..6bdbec1203c 100644
--- a/spec/helpers/nav_helper_spec.rb
+++ b/spec/helpers/nav_helper_spec.rb
@@ -117,4 +117,24 @@ describe NavHelper, :do_not_mock_admin_mode do
it { is_expected.to all(be_a(String)) }
end
+
+ describe '.show_user_notification_dot?' do
+ subject { helper.show_user_notification_dot? }
+
+ context 'when experiment is disabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:ci_notification_dot).and_return(false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when experiment is enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:ci_notification_dot).and_return(true)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/lib/api/entities/release_spec.rb b/spec/lib/api/entities/release_spec.rb
index f0bbaa35efe..c45dbc15856 100644
--- a/spec/lib/api/entities/release_spec.rb
+++ b/spec/lib/api/entities/release_spec.rb
@@ -4,26 +4,29 @@ require 'spec_helper'
describe API::Entities::Release do
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
- let(:entity) { described_class.new(release, current_user: user) }
-
- describe 'evidence' do
- let(:release) { create(:release, :with_evidence, project: project) }
-
- subject { entity.as_json }
+ let_it_be(:release) { create(:release, :with_evidence, project: project) }
+ let(:evidence) { release.evidences.first }
+ let(:user) { create(:user) }
+ let(:entity) { described_class.new(release, current_user: user).as_json }
+ describe 'evidences' do
context 'when the current user can download code' do
+ let(:entity_evidence) { entity[:evidences].first }
+
it 'exposes the evidence sha and the json path' do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?)
.with(user, :download_code, project).and_return(true)
- expect(subject[:evidence_sha]).to eq(release.evidence_sha)
- expect(subject[:assets][:evidence_file_path]).to eq(
- Gitlab::Routing.url_helpers.evidence_project_release_url(project,
- release.tag,
- format: :json)
- )
+ expect(entity_evidence[:sha]).to eq(evidence.summary_sha)
+ expect(entity_evidence[:collected_at]).to eq(evidence.collected_at)
+ expect(entity_evidence[:filepath]).to eq(
+ Gitlab::Routing.url_helpers.namespace_project_evidence_url(
+ namespace_id: project.namespace,
+ project_id: project,
+ tag: release,
+ id: evidence.id,
+ format: :json))
end
end
@@ -33,8 +36,7 @@ describe API::Entities::Release do
allow(Ability).to receive(:allowed?)
.with(user, :download_code, project).and_return(false)
- expect(subject.keys).not_to include(:evidence_sha)
- expect(subject[:assets].keys).not_to include(:evidence_file_path)
+ expect(entity.keys).not_to include(:evidences)
end
end
end
@@ -45,7 +47,7 @@ describe API::Entities::Release do
let(:issue_title) { 'title="%s"' % issue.title }
let(:release) { create(:release, project: project, description: "Now shipping #{issue.to_reference}") }
- subject(:description_html) { entity.as_json[:description_html] }
+ subject(:description_html) { entity.as_json['description_html'] }
it 'renders special references if current user has access' do
project.add_reporter(user)
diff --git a/spec/lib/event_filter_spec.rb b/spec/lib/event_filter_spec.rb
index e35698f6030..da6e1f9458f 100644
--- a/spec/lib/event_filter_spec.rb
+++ b/spec/lib/event_filter_spec.rb
@@ -28,6 +28,8 @@ describe EventFilter do
let_it_be(:comments_event) { create(:event, :commented, project: public_project, target: public_project) }
let_it_be(:joined_event) { create(:event, :joined, project: public_project, target: public_project) }
let_it_be(:left_event) { create(:event, :left, project: public_project, target: public_project) }
+ let_it_be(:wiki_page_event) { create(:wiki_page_event) }
+ let_it_be(:wiki_page_update_event) { create(:wiki_page_event, :updated) }
let(:filtered_events) { described_class.new(filter).apply_filter(Event.all) }
@@ -77,6 +79,34 @@ describe EventFilter do
it 'returns all events' do
expect(filtered_events).to eq(Event.all)
end
+
+ context 'the :wiki_events filter is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not return wiki events' do
+ expect(filtered_events).to eq(Event.not_wiki_page)
+ end
+ end
+ end
+
+ context 'with the "wiki" filter' do
+ let(:filter) { described_class::WIKI }
+
+ it 'returns only wiki page events' do
+ expect(filtered_events).to contain_exactly(wiki_page_event, wiki_page_update_event)
+ end
+
+ context 'the :wiki_events filter is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not return wiki events' do
+ expect(filtered_events).not_to include(wiki_page_event, wiki_page_update_event)
+ end
+ end
end
context 'with an unknown filter' do
@@ -85,6 +115,16 @@ describe EventFilter do
it 'returns all events' do
expect(filtered_events).to eq(Event.all)
end
+
+ context 'the :wiki_events filter is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not return wiki events' do
+ expect(filtered_events).to eq(Event.not_wiki_page)
+ end
+ end
end
context 'with a nil filter' do
@@ -93,6 +133,16 @@ describe EventFilter do
it 'returns all events' do
expect(filtered_events).to eq(Event.all)
end
+
+ context 'the :wiki_events filter is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not return wiki events' do
+ expect(filtered_events).to eq(Event.not_wiki_page)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index b3f279344b1..0ed5a1e7b49 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -94,7 +94,7 @@ releases:
- links
- milestone_releases
- milestones
-- evidence
+- evidences
links:
- release
project_members:
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 5b0444c394e..533458afd73 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -134,7 +134,7 @@ Release:
- created_at
- updated_at
- released_at
-Evidence:
+Releases::Evidence:
- id
- summary
- created_at
diff --git a/spec/models/event_collection_spec.rb b/spec/models/event_collection_spec.rb
index e6f80a4c4d0..6d1954700bf 100644
--- a/spec/models/event_collection_spec.rb
+++ b/spec/models/event_collection_spec.rb
@@ -8,22 +8,68 @@ describe EventCollection do
let_it_be(:project) { create(:project_empty_repo, group: group) }
let_it_be(:projects) { Project.where(id: project.id) }
let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request) }
context 'with project events' do
- before do
- 20.times do
- event = create(:push_event, project: project, author: user)
-
- create(:push_event_payload, event: event)
+ let_it_be(:push_event_payloads) do
+ Array.new(9) do
+ create(:push_event_payload,
+ event: create(:push_event, project: project, author: user))
end
-
- create(:closed_issue_event, project: project, author: user)
end
- it 'returns an Array of events' do
+ let_it_be(:merge_request_events) { create_list(:event, 10, :commented, project: project, target: merge_request) }
+ let_it_be(:closed_issue_event) { create(:closed_issue_event, project: project, author: user) }
+ let_it_be(:wiki_page_event) { create(:wiki_page_event, project: project) }
+ let(:push_events) { push_event_payloads.map(&:event) }
+
+ it 'returns an Array of events', :aggregate_failures do
+ most_recent_20_events = [
+ wiki_page_event,
+ closed_issue_event,
+ *push_events,
+ *merge_request_events
+ ].sort_by(&:id).reverse.take(20)
events = described_class.new(projects).to_a
expect(events).to be_an_instance_of(Array)
+ expect(events).to match_array(most_recent_20_events)
+ end
+
+ context 'the wiki_events feature flag is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'omits the wiki page events when using to_a' do
+ events = described_class.new(projects).to_a
+
+ expect(events).not_to include(wiki_page_event)
+ end
+
+ it 'omits the wiki page events when using all_project_events' do
+ events = described_class.new(projects).all_project_events
+
+ expect(events).not_to include(wiki_page_event)
+ end
+ end
+
+ context 'the wiki_events feature flag is enabled' do
+ before do
+ stub_feature_flags(wiki_events: true)
+ end
+
+ it 'includes the wiki page events when using to_a' do
+ events = described_class.new(projects).to_a
+
+ expect(events).to include(wiki_page_event)
+ end
+
+ it 'includes the wiki page events when using all_project_events' do
+ events = described_class.new(projects).all_project_events
+
+ expect(events).to include(wiki_page_event)
+ end
end
it 'applies a limit to the number of events' do
@@ -44,12 +90,25 @@ describe EventCollection do
expect(events).to be_empty
end
- it 'allows filtering of events using an EventFilter' do
+ it 'allows filtering of events using an EventFilter, returning single item' do
filter = EventFilter.new(EventFilter::ISSUE)
events = described_class.new(projects, filter: filter).to_a
- expect(events.length).to eq(1)
- expect(events[0].action).to eq(Event::CLOSED)
+ expect(events).to contain_exactly(closed_issue_event)
+ end
+
+ it 'allows filtering of events using an EventFilter, returning several items' do
+ filter = EventFilter.new(EventFilter::COMMENTS)
+ events = described_class.new(projects, filter: filter).to_a
+
+ expect(events).to match_array(merge_request_events)
+ end
+
+ it 'allows filtering of events using an EventFilter, returning pushes' do
+ filter = EventFilter.new(EventFilter::PUSH)
+ events = described_class.new(projects, filter: filter).to_a
+
+ expect(events).to match_array(push_events)
end
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index b2676a79b55..3239c7a843a 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -454,9 +454,10 @@ describe Event do
end
end
- describe '.for_wiki_page' do
+ describe 'wiki_page predicate scopes' do
let_it_be(:events) do
[
+ create(:push_event),
create(:closed_issue_event),
create(:wiki_page_event),
create(:closed_issue_event),
@@ -465,10 +466,22 @@ describe Event do
]
end
- it 'only contains the wiki page events' do
- wiki_events = events.select(&:wiki_page?)
+ describe '.for_wiki_page' do
+ it 'only contains the wiki page events' do
+ wiki_events = events.select(&:wiki_page?)
- expect(described_class.for_wiki_page).to match_array(wiki_events)
+ expect(events).not_to match_array(wiki_events)
+ expect(described_class.for_wiki_page).to match_array(wiki_events)
+ end
+ end
+
+ describe '.not_wiki_page' do
+ it 'does not contain the wiki page events' do
+ non_wiki_events = events.reject(&:wiki_page?)
+
+ expect(events).not_to match_array(non_wiki_events)
+ expect(described_class.not_wiki_page).to match_array(non_wiki_events)
+ end
end
end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 3884b8138be..8b1b738ab58 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Release do
it { is_expected.to have_many(:links).class_name('Releases::Link') }
it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:milestone_releases) }
- it { is_expected.to have_one(:evidence) }
+ it { is_expected.to have_many(:evidences).class_name('Releases::Evidence') }
end
describe 'validation' do
@@ -97,7 +97,7 @@ RSpec.describe Release do
describe '#create_evidence!' do
context 'when a release is created' do
it 'creates one Evidence object too' do
- expect { release_with_evidence }.to change(Evidence, :count).by(1)
+ expect { release_with_evidence }.to change(Releases::Evidence, :count).by(1)
end
end
end
@@ -106,7 +106,7 @@ RSpec.describe Release do
it 'also deletes the associated evidence' do
release_with_evidence
- expect { release_with_evidence.destroy }.to change(Evidence, :count).by(-1)
+ expect { release_with_evidence.destroy }.to change(Releases::Evidence, :count).by(-1)
end
end
end
@@ -155,7 +155,7 @@ RSpec.describe Release do
context 'when a release was created with evidence collection' do
let!(:release) { create(:release, :with_evidence) }
- it { is_expected.to eq(release.evidence.summary_sha) }
+ it { is_expected.to eq(release.evidences.first.summary_sha) }
end
end
@@ -171,7 +171,7 @@ RSpec.describe Release do
context 'when a release was created with evidence collection' do
let!(:release) { create(:release, :with_evidence) }
- it { is_expected.to eq(release.evidence.summary) }
+ it { is_expected.to eq(release.evidences.first.summary) }
end
end
diff --git a/spec/models/evidence_spec.rb b/spec/models/releases/evidence_spec.rb
index 8f534517fc1..d38d2021117 100644
--- a/spec/models/evidence_spec.rb
+++ b/spec/models/releases/evidence_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Evidence do
+describe Releases::Evidence do
let_it_be(:project) { create(:project) }
let(:release) { create(:release, project: project) }
let(:schema_file) { 'evidences/evidence' }
diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb
index 82f312622ff..d1f023b8760 100644
--- a/spec/presenters/release_presenter_spec.rb
+++ b/spec/presenters/release_presenter_spec.rb
@@ -112,28 +112,4 @@ describe ReleasePresenter do
it { is_expected.to be_nil }
end
end
-
- describe '#evidence_file_path' do
- subject { presenter.evidence_file_path }
-
- context 'without evidence' do
- it { is_expected.to be_falsy }
- end
-
- context 'with evidence' do
- let(:release) { create :release, :with_evidence, project: project }
-
- specify do
- is_expected.to match /#{evidence_project_release_url(project, release.tag, format: :json)}/
- end
- end
-
- context 'when a tag contains a slash' do
- let(:release) { create :release, :with_evidence, project: project, tag: 'debian/2.4.0-1' }
-
- specify do
- is_expected.to match /#{evidence_project_release_url(project, CGI.escape(release.tag), format: :json)}/
- end
- end
- end
end
diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb
index acf3bb3482a..decdcc66327 100644
--- a/spec/requests/api/events_spec.rb
+++ b/spec/requests/api/events_spec.rb
@@ -114,6 +114,26 @@ describe API::Events do
expect(json_response.size).to eq(1)
end
+ context 'when the list of events includes wiki page events' do
+ it 'returns information about the wiki event', :aggregate_failures do
+ page = create(:wiki_page, project: private_project)
+ [Event::CREATED, Event::UPDATED, Event::DESTROYED].each do |action|
+ create(:wiki_page_event, wiki_page: page, action: action, author: user)
+ end
+
+ get api("/users/#{user.id}/events", user)
+
+ wiki_events = json_response.select { |e| e['target_type'] == 'WikiPage::Meta' }
+ action_names = wiki_events.map { |e| e['action_name'] }
+ titles = wiki_events.map { |e| e['target_title'] }
+ slugs = wiki_events.map { |e| e.dig('wiki_page', 'slug') }
+
+ expect(action_names).to contain_exactly('created', 'updated', 'destroyed')
+ expect(titles).to all(eq(page.title))
+ expect(slugs).to all(eq(page.slug))
+ end
+ end
+
context 'when the list of events includes push events' do
let(:event) do
create(:push_event, author: user, project: private_project)
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
index a38d1857076..c7b537a9923 100644
--- a/spec/requests/api/graphql/group_query_spec.rb
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -51,6 +51,7 @@ describe 'getting group information', :do_not_mock_admin_mode do
it "returns one of user1's groups" do
project = create(:project, namespace: group2, path: 'Foo')
+ issue = create(:issue, project: create(:project, group: group1))
create(:project_group_link, project: project, group: group1)
post_graphql(group_query(group1), current_user: user1)
@@ -67,6 +68,8 @@ describe 'getting group information', :do_not_mock_admin_mode do
expect(graphql_data['group']['fullName']).to eq(group1.full_name)
expect(graphql_data['group']['fullPath']).to eq(group1.full_path)
expect(graphql_data['group']['parentId']).to eq(group1.parent_id)
+ expect(graphql_data['group']['issues']['nodes'].count).to eq(1)
+ expect(graphql_data['group']['issues']['nodes'][0]['iid']).to eq(issue.iid.to_s)
end
it "does not return a non existing group" do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index cec4995c620..ea60f783b48 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -71,6 +71,7 @@ describe API::Groups do
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
+ expect(json_response.first['created_at']).to be_present
expect(json_response)
.to satisfy_one { |group| group['name'] == group1.name }
end
@@ -121,6 +122,15 @@ describe API::Groups do
expect(json_response).to be_an Array
expect(json_response.first).not_to include 'statistics'
end
+
+ it "includes a created_at timestamp" do
+ get api("/groups", user1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first['created_at']).to be_present
+ end
end
context "when authenticated as admin" do
@@ -152,6 +162,15 @@ describe API::Groups do
expect(json_response.first).not_to include('statistics')
end
+ it "includes a created_at timestamp" do
+ get api("/groups", admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first['created_at']).to be_present
+ end
+
it "includes statistics if requested" do
attributes = {
storage_size: 1158,
@@ -357,6 +376,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).not_to include('runners_token')
+ expect(json_response).to include('created_at')
end
it 'returns only public projects in the group' do
@@ -407,6 +427,7 @@ describe API::Groups do
expect(json_response['full_name']).to eq(group1.full_name)
expect(json_response['full_path']).to eq(group1.full_path)
expect(json_response['parent_id']).to eq(group1.parent_id)
+ expect(json_response['created_at']).to be_present
expect(json_response['projects']).to be_an Array
expect(json_response['projects'].length).to eq(2)
expect(json_response['shared_projects']).to be_an Array
@@ -613,6 +634,7 @@ describe API::Groups do
expect(json_response['subgroup_creation_level']).to eq("maintainer")
expect(json_response['request_access_enabled']).to eq(true)
expect(json_response['parent_id']).to eq(nil)
+ expect(json_response['created_at']).to be_present
expect(json_response['projects']).to be_an Array
expect(json_response['projects'].length).to eq(2)
expect(json_response['shared_projects']).to be_an Array
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 41999ca6e60..e66e999dc27 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -104,6 +104,21 @@ describe API::Releases do
expect(json_response.first['upcoming_release']).to eq(false)
end
+ it 'avoids N+1 queries' do
+ create(:release, :with_evidence, project: project, tag: 'v0.1', author: maintainer)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ get api("/projects/#{project.id}/releases", maintainer)
+ end.count
+
+ create(:release, :with_evidence, project: project, tag: 'v0.1', author: maintainer)
+ create(:release, :with_evidence, project: project, tag: 'v0.1', author: maintainer)
+
+ expect do
+ get api("/projects/#{project.id}/releases", maintainer)
+ end.not_to exceed_query_limit(control_count)
+ end
+
context 'when tag does not exist in git repository' do
let!(:release) { create(:release, project: project, tag: 'v1.1.5') }
@@ -725,7 +740,7 @@ describe API::Releases do
end
it 'does not create an Evidence object', :sidekiq_inline do
- expect { subject }.not_to change(Evidence, :count)
+ expect { subject }.not_to change(Releases::Evidence, :count)
end
it 'is a historical release' do
@@ -755,7 +770,7 @@ describe API::Releases do
end
it 'creates Evidence', :sidekiq_inline do
- expect { subject }.to change(Evidence, :count).by(1)
+ expect { subject }.to change(Releases::Evidence, :count).by(1)
end
it 'is not a historical release' do
@@ -785,7 +800,7 @@ describe API::Releases do
end
it 'creates Evidence', :sidekiq_inline do
- expect { subject }.to change(Evidence, :count).by(1)
+ expect { subject }.to change(Releases::Evidence, :count).by(1)
end
it 'is not a historical release' do
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index a8ddca0cdf3..0a8a4d5bf58 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -153,6 +153,46 @@ describe EventCreateService do
end
end
+ describe '#wiki_event' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:wiki_page) { create(:wiki_page) }
+ let_it_be(:meta) { create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
+
+ Event::WIKI_ACTIONS.each do |action|
+ context "The action is #{action}" do
+ let(:event) { service.wiki_event(meta, user, action) }
+
+ it 'creates the event' do
+ expect(event).to have_attributes(
+ wiki_page?: true,
+ valid?: true,
+ persisted?: true,
+ action: action,
+ wiki_page: wiki_page
+ )
+ end
+
+ context 'the feature is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not create the event' do
+ expect { event }.not_to change(Event, :count)
+ end
+ end
+ end
+ end
+
+ (Event::ACTIONS.values - Event::WIKI_ACTIONS).each do |bad_action|
+ context "The action is #{bad_action}" do
+ it 'raises an error' do
+ expect { service.wiki_event(meta, user, bad_action) }.to raise_error(described_class::IllegalActionError)
+ end
+ end
+ end
+ end
+
describe '#push', :clean_gitlab_redis_shared_state do
let(:project) { create(:project) }
let(:user) { create(:user) }
diff --git a/spec/services/wiki_pages/base_service_spec.rb b/spec/services/wiki_pages/base_service_spec.rb
index 2e70246c6f2..4c44c195ac8 100644
--- a/spec/services/wiki_pages/base_service_spec.rb
+++ b/spec/services/wiki_pages/base_service_spec.rb
@@ -6,22 +6,24 @@ describe WikiPages::BaseService do
let(:project) { double('project') }
let(:user) { double('user') }
- subject(:service) { described_class.new(project, user, {}) }
-
describe '#increment_usage' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
error = counter::UnknownEvent
- it 'raises an error on unknown events' do
- expect { subject.send(:increment_usage, :bad_event) }.to raise_error error
- end
+ let(:subject) { bad_service_class.new(project, user, {}) }
- context 'the event is valid' do
- counter::KNOWN_EVENTS.each do |e|
- it "updates the #{e} counter" do
- expect { subject.send(:increment_usage, e) }.to change { counter.read(e) }
+ context 'the class implements usage_counter_action incorrectly' do
+ let(:bad_service_class) do
+ Class.new(described_class) do
+ def usage_counter_action
+ :bad_event
+ end
end
end
+
+ it 'raises an error on unknown events' do
+ expect { subject.send(:increment_usage) }.to raise_error(error)
+ end
end
end
end
diff --git a/spec/services/wiki_pages/create_service_spec.rb b/spec/services/wiki_pages/create_service_spec.rb
index ef03a2e9788..d63d62e9492 100644
--- a/spec/services/wiki_pages/create_service_spec.rb
+++ b/spec/services/wiki_pages/create_service_spec.rb
@@ -5,19 +5,16 @@ require 'spec_helper'
describe WikiPages::CreateService do
let(:project) { create(:project, :wiki_repo) }
let(:user) { create(:user) }
+ let(:page_title) { 'Title' }
let(:opts) do
{
- title: 'Title',
+ title: page_title,
content: 'Content for wiki page',
format: 'markdown'
}
end
- let(:bad_opts) do
- { title: '' }
- end
-
subject(:service) { described_class.new(project, user, opts) }
before do
@@ -35,8 +32,7 @@ describe WikiPages::CreateService do
end
it 'executes webhooks' do
- expect(service).to receive(:execute_hooks).once
- .with(instance_of(WikiPage), 'create')
+ expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute
end
@@ -47,8 +43,41 @@ describe WikiPages::CreateService do
expect { service.execute }.to change { counter.read(:create) }.by 1
end
+ shared_examples 'correct event created' do
+ it 'creates appropriate events' do
+ expect { service.execute }.to change { Event.count }.by 1
+
+ expect(Event.recent.first).to have_attributes(
+ action: Event::CREATED,
+ target: have_attributes(canonical_slug: page_title)
+ )
+ end
+ end
+
+ context 'the new page is at the top level' do
+ let(:page_title) { 'root-level-page' }
+
+ include_examples 'correct event created'
+ end
+
+ context 'the new page is in a subsection' do
+ let(:page_title) { 'subsection/page' }
+
+ include_examples 'correct event created'
+ end
+
+ context 'the feature is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not record the activity' do
+ expect { service.execute }.not_to change(Event, :count)
+ end
+ end
+
context 'when the options are bad' do
- subject(:service) { described_class.new(project, user, bad_opts) }
+ let(:page_title) { '' }
it 'does not count a creation event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
@@ -56,6 +85,10 @@ describe WikiPages::CreateService do
expect { service.execute }.not_to change { counter.read(:create) }
end
+ it 'does not record the activity' do
+ expect { service.execute }.not_to change(Event, :count)
+ end
+
it 'reports the error' do
expect(service.execute).to be_invalid
.and have_attributes(errors: be_present)
diff --git a/spec/services/wiki_pages/destroy_service_spec.rb b/spec/services/wiki_pages/destroy_service_spec.rb
index 350a7eb123b..e205bedfdb9 100644
--- a/spec/services/wiki_pages/destroy_service_spec.rb
+++ b/spec/services/wiki_pages/destroy_service_spec.rb
@@ -15,8 +15,7 @@ describe WikiPages::DestroyService do
describe '#execute' do
it 'executes webhooks' do
- expect(service).to receive(:execute_hooks).once
- .with(instance_of(WikiPage), 'delete')
+ expect(service).to receive(:execute_hooks).once.with(page)
service.execute(page)
end
@@ -27,10 +26,29 @@ describe WikiPages::DestroyService do
expect { service.execute(page) }.to change { counter.read(:delete) }.by 1
end
+ it 'creates a new wiki page deletion event' do
+ expect { service.execute(page) }.to change { Event.count }.by 1
+
+ expect(Event.recent.first).to have_attributes(
+ action: Event::DESTROYED,
+ target: have_attributes(canonical_slug: page.slug)
+ )
+ end
+
it 'does not increment the delete count if the deletion failed' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(nil) }.not_to change { counter.read(:delete) }
end
end
+
+ context 'the feature is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not record the activity' do
+ expect { service.execute(page) }.not_to change(Event, :count)
+ end
+ end
end
diff --git a/spec/services/wiki_pages/update_service_spec.rb b/spec/services/wiki_pages/update_service_spec.rb
index d5f46e7b2db..3eb486833e6 100644
--- a/spec/services/wiki_pages/update_service_spec.rb
+++ b/spec/services/wiki_pages/update_service_spec.rb
@@ -6,20 +6,17 @@ describe WikiPages::UpdateService do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
+ let(:page_title) { 'New Title' }
let(:opts) do
{
content: 'New content for wiki page',
format: 'markdown',
message: 'New wiki message',
- title: 'New Title'
+ title: page_title
}
end
- let(:bad_opts) do
- { title: '' }
- end
-
subject(:service) { described_class.new(project, user, opts) }
before do
@@ -34,12 +31,11 @@ describe WikiPages::UpdateService do
expect(updated_page.message).to eq(opts[:message])
expect(updated_page.content).to eq(opts[:content])
expect(updated_page.format).to eq(opts[:format].to_sym)
- expect(updated_page.title).to eq(opts[:title])
+ expect(updated_page.title).to eq(page_title)
end
it 'executes webhooks' do
- expect(service).to receive(:execute_hooks).once
- .with(instance_of(WikiPage), 'update')
+ expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute(page)
end
@@ -50,8 +46,42 @@ describe WikiPages::UpdateService do
expect { service.execute page }.to change { counter.read(:update) }.by 1
end
+ shared_examples 'adds activity event' do
+ it 'adds a new wiki page activity event' do
+ expect { service.execute(page) }.to change { Event.count }.by 1
+
+ expect(Event.recent.first).to have_attributes(
+ action: Event::UPDATED,
+ wiki_page: page,
+ target_title: page.title
+ )
+ end
+ end
+
+ context 'the page is at the top level' do
+ let(:page_title) { 'Top level page' }
+
+ include_examples 'adds activity event'
+ end
+
+ context 'the page is in a subsection' do
+ let(:page_title) { 'Subsection / secondary page' }
+
+ include_examples 'adds activity event'
+ end
+
+ context 'the feature is disabled' do
+ before do
+ stub_feature_flags(wiki_events: false)
+ end
+
+ it 'does not record the activity' do
+ expect { service.execute(page) }.not_to change(Event, :count)
+ end
+ end
+
context 'when the options are bad' do
- subject(:service) { described_class.new(project, user, bad_opts) }
+ let(:page_title) { '' }
it 'does not count an edit event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
@@ -59,6 +89,10 @@ describe WikiPages::UpdateService do
expect { service.execute page }.not_to change { counter.read(:update) }
end
+ it 'does not record the activity' do
+ expect { service.execute page }.not_to change(Event, :count)
+ end
+
it 'reports the error' do
expect(service.execute page).to be_invalid
.and have_attributes(errors: be_present)
diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb
index 7a5a188ab4d..ff3b02dc3f6 100644
--- a/spec/support/helpers/stub_experiments.rb
+++ b/spec/support/helpers/stub_experiments.rb
@@ -8,6 +8,8 @@ module StubExperiments
# Examples
# - `stub_experiment(signup_flow: false)` ... Disable `signup_flow` experiment globally.
def stub_experiment(experiments)
+ allow(Gitlab::Experimentation).to receive(:enabled?).and_call_original
+
experiments.each do |experiment_key, enabled|
allow(Gitlab::Experimentation).to receive(:enabled?).with(experiment_key) { enabled }
end
@@ -20,6 +22,8 @@ module StubExperiments
# Examples
# - `stub_experiment_for_user(signup_flow: false)` ... Disable `signup_flow` experiment for user.
def stub_experiment_for_user(experiments)
+ allow(Gitlab::Experimentation).to receive(:enabled_for_user?).and_call_original
+
experiments.each do |experiment_key, enabled|
allow(Gitlab::Experimentation).to receive(:enabled_for_user?).with(experiment_key, anything) { enabled }
end
diff --git a/spec/workers/create_evidence_worker_spec.rb b/spec/workers/create_evidence_worker_spec.rb
index 364b2098251..9b8314122cd 100644
--- a/spec/workers/create_evidence_worker_spec.rb
+++ b/spec/workers/create_evidence_worker_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe CreateEvidenceWorker do
let!(:release) { create(:release) }
- it 'creates a new Evidence' do
- expect { described_class.new.perform(release.id) }.to change(Evidence, :count).by(1)
+ it 'creates a new Evidence record' do
+ expect { described_class.new.perform(release.id) }.to change(Releases::Evidence, :count).by(1)
end
end