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-02-25 00:09:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-25 00:09:08 +0300
commit7671216b60e2796a050358ff808b4a0c2de3d22f (patch)
tree605dfc1339a3cd7dc7353ac6d725191086a9acca /spec
parentc2367afbf57ebc65d5b78a743b5d6a91f0aece9f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/blob/pipeline_tour_success_spec.js40
-rw-r--r--spec/frontend/helpers/tracking_helper.js2
-rw-r--r--spec/frontend/tracking_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js55
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_tour_spec.js143
-rw-r--r--spec/frontend/vue_mr_widget/components/states/pipeline_tour_mock_data.js10
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js90
-rw-r--r--spec/helpers/blob_helper_spec.rb86
-rw-r--r--spec/javascripts/helpers/tracking_helper.js2
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js1
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/file_row_spec.js87
-rw-r--r--spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb6
-rw-r--r--spec/requests/api/version_spec.rb46
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb5
-rw-r--r--spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb6
-rw-r--r--spec/uploaders/import_export_uploader_spec.rb6
17 files changed, 484 insertions, 115 deletions
diff --git a/spec/frontend/blob/pipeline_tour_success_spec.js b/spec/frontend/blob/pipeline_tour_success_spec.js
new file mode 100644
index 00000000000..f6783b31a73
--- /dev/null
+++ b/spec/frontend/blob/pipeline_tour_success_spec.js
@@ -0,0 +1,40 @@
+import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
+import { shallowMount } from '@vue/test-utils';
+import Cookies from 'js-cookie';
+import { GlSprintf, GlModal } from '@gitlab/ui';
+
+describe('PipelineTourSuccessModal', () => {
+ let wrapper;
+ let cookieSpy;
+ const goToPipelinesPath = 'some_pipeline_path';
+ const commitCookie = 'some_cookie';
+
+ beforeEach(() => {
+ wrapper = shallowMount(pipelineTourSuccess, {
+ propsData: {
+ goToPipelinesPath,
+ commitCookie,
+ },
+ });
+
+ cookieSpy = jest.spyOn(Cookies, 'remove');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has expected structure', () => {
+ const modal = wrapper.find(GlModal);
+ const sprintf = modal.find(GlSprintf);
+
+ expect(modal.attributes('title')).toContain("That's it, well done!");
+ expect(sprintf.exists()).toBe(true);
+ });
+
+ it('calls to remove cookie', () => {
+ wrapper.vm.disableModalFromRenderingAgain();
+
+ expect(cookieSpy).toHaveBeenCalledWith(commitCookie);
+ });
+});
diff --git a/spec/frontend/helpers/tracking_helper.js b/spec/frontend/helpers/tracking_helper.js
index 68c1bd2dbca..bd3bd24028c 100644
--- a/spec/frontend/helpers/tracking_helper.js
+++ b/spec/frontend/helpers/tracking_helper.js
@@ -8,7 +8,7 @@ let handlers;
export function mockTracking(category = '_category_', documentOverride, spyMethod) {
document = documentOverride || window.document;
window.snowplow = () => {};
- Tracking.bindDocument(category, document);
+ handlers = Tracking.bindDocument(category, document);
return spyMethod ? spyMethod(Tracking, 'event') : null;
}
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index c3c52844c2c..30a8e138df2 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -226,6 +226,14 @@ describe('Tracking', () => {
};
});
+ it('calls the event method with no category or action defined', () => {
+ mixin.trackingCategory = mixin.trackingCategory();
+ mixin.trackingOptions = mixin.trackingOptions();
+
+ mixin.track();
+ expect(eventSpy).toHaveBeenCalledWith(undefined, undefined, {});
+ });
+
it('calls the event method', () => {
mixin.trackingCategory = mixin.trackingCategory();
mixin.trackingOptions = mixin.trackingOptions();
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
index 77293a5b187..8b0253dc01a 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
@@ -1,16 +1,24 @@
import { mount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import suggestPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue';
+import stubChildren from 'helpers/stub_children';
+import PipelineTourState from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_tour.vue';
import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
describe('MRWidgetHeader', () => {
let wrapper;
const pipelinePath = '/foo/bar/add/pipeline/path';
+ const pipelineSvgPath = '/foo/bar/pipeline/svg/path';
+ const humanAccess = 'maintainer';
const iconName = 'status_notfound';
beforeEach(() => {
wrapper = mount(suggestPipelineComponent, {
- propsData: { pipelinePath },
+ propsData: { pipelinePath, pipelineSvgPath, humanAccess },
+ stubs: {
+ ...stubChildren(PipelineTourState),
+ },
});
});
@@ -22,30 +30,47 @@ describe('MRWidgetHeader', () => {
it('renders add pipeline file link', () => {
const link = wrapper.find(GlLink);
- return wrapper.vm.$nextTick().then(() => {
- expect(link.exists()).toBe(true);
- expect(link.attributes().href).toBe(pipelinePath);
- });
+ expect(link.exists()).toBe(true);
+ expect(link.attributes().href).toBe(pipelinePath);
});
it('renders the expected text', () => {
const messageText = /\s*No pipeline\s*Add the .gitlab-ci.yml file\s*to create one./;
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.text()).toMatch(messageText);
- });
+ expect(wrapper.text()).toMatch(messageText);
});
it('renders widget icon', () => {
const icon = wrapper.find(MrWidgetIcon);
- return wrapper.vm.$nextTick().then(() => {
- expect(icon.exists()).toBe(true);
- expect(icon.props()).toEqual(
- expect.objectContaining({
- name: iconName,
- }),
- );
+ expect(icon.exists()).toBe(true);
+ expect(icon.props()).toEqual(
+ expect.objectContaining({
+ name: iconName,
+ }),
+ );
+ });
+
+ describe('tracking', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('send an event when ok button is clicked', () => {
+ const link = wrapper.find(GlLink);
+ triggerEvent(link.element);
+
+ expect(spy).toHaveBeenCalledWith('_category_', 'click_link', {
+ label: 'no_pipeline_noticed',
+ property: humanAccess,
+ value: '30',
+ });
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_tour_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_tour_spec.js
new file mode 100644
index 00000000000..e8f95e099cc
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_tour_spec.js
@@ -0,0 +1,143 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlPopover } from '@gitlab/ui';
+import Cookies from 'js-cookie';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
+import pipelineTourState from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_tour.vue';
+import { popoverProps, cookieKey } from './pipeline_tour_mock_data';
+
+describe('MRWidgetPipelineTour', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ describe(`when ${cookieKey} cookie is set`, () => {
+ beforeEach(() => {
+ Cookies.set(cookieKey, true);
+ wrapper = shallowMount(pipelineTourState, {
+ propsData: popoverProps,
+ });
+ });
+
+ it('does not render the popover', () => {
+ const popover = wrapper.find(GlPopover);
+
+ expect(popover.exists()).toBe(false);
+ });
+
+ describe('tracking', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+ it('does not call tracking', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe(`when ${cookieKey} cookie is not set`, () => {
+ const findOkBtn = () => wrapper.find({ ref: 'ok' });
+ const findDismissBtn = () => wrapper.find({ ref: 'no-thanks' });
+
+ beforeEach(() => {
+ Cookies.remove(cookieKey);
+ wrapper = shallowMount(pipelineTourState, {
+ propsData: popoverProps,
+ });
+ });
+
+ it('renders the popover', () => {
+ const popover = wrapper.find(GlPopover);
+
+ expect(popover.exists()).toBe(true);
+ });
+
+ it('renders the show me how button', () => {
+ const button = findOkBtn();
+
+ expect(button.exists()).toBe(true);
+ expect(button.attributes().category).toBe('primary');
+ });
+
+ it('renders the dismiss button', () => {
+ const button = findDismissBtn();
+
+ expect(button.exists()).toBe(true);
+ expect(button.attributes().category).toBe('secondary');
+ });
+
+ it('renders the empty pipelines image', () => {
+ const image = wrapper.find('img');
+
+ expect(image.exists()).toBe(true);
+ expect(image.attributes().src).toBe(popoverProps.pipelineSvgPath);
+ });
+
+ describe('tracking', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('send event for basic view of popover', () => {
+ document.body.dataset.page = 'projects:merge_requests:show';
+
+ wrapper.vm.trackOnShow();
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, undefined, {
+ label: popoverProps.trackLabel,
+ property: popoverProps.humanAccess,
+ });
+ });
+
+ it('send an event when ok button is clicked', () => {
+ const okBtn = findOkBtn();
+ triggerEvent(okBtn.element);
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
+ label: popoverProps.trackLabel,
+ property: popoverProps.humanAccess,
+ value: '10',
+ });
+ });
+
+ it('send an event when dismiss button is clicked', () => {
+ const dismissBtn = findDismissBtn();
+ triggerEvent(dismissBtn.element);
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
+ label: popoverProps.trackLabel,
+ property: popoverProps.humanAccess,
+ value: '20',
+ });
+ });
+ });
+
+ describe('dismissPopover', () => {
+ it('updates popoverDismissed', () => {
+ const button = findDismissBtn();
+ const popover = wrapper.find(GlPopover);
+ button.vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(Cookies.get(cookieKey)).toBe('true');
+ expect(popover.exists()).toBe(false);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/pipeline_tour_mock_data.js b/spec/frontend/vue_mr_widget/components/states/pipeline_tour_mock_data.js
new file mode 100644
index 00000000000..39bc89e459c
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/states/pipeline_tour_mock_data.js
@@ -0,0 +1,10 @@
+export const popoverProps = {
+ pipelinePath: '/foo/bar/add/pipeline/path',
+ pipelineSvgPath: 'assets/illustrations/something.svg',
+ humanAccess: 'maintainer',
+ popoverTarget: 'suggest-popover',
+ popoverContainer: 'suggest-pipeline',
+ trackLabel: 'some_tracking_label',
+};
+
+export const cookieKey = 'suggest_pipeline_dismissed';
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
new file mode 100644
index 00000000000..420281e844c
--- /dev/null
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -0,0 +1,90 @@
+import { file } from 'jest/ide/helpers';
+import FileRow from '~/vue_shared/components/file_row.vue';
+import { mount } from '@vue/test-utils';
+
+describe('File row component', () => {
+ let wrapper;
+
+ function createComponent(propsData) {
+ wrapper = mount(FileRow, {
+ propsData,
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders name', () => {
+ const fileName = 't4';
+ createComponent({
+ file: file(fileName),
+ level: 0,
+ });
+
+ const name = wrapper.find('.file-row-name');
+
+ expect(name.text().trim()).toEqual(fileName);
+ });
+
+ it('emits toggleTreeOpen on click', () => {
+ const fileName = 't3';
+ createComponent({
+ file: {
+ ...file(fileName),
+ type: 'tree',
+ },
+ level: 0,
+ });
+ jest.spyOn(wrapper.vm, '$emit');
+
+ wrapper.element.click();
+
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('toggleTreeOpen', fileName);
+ });
+
+ it('calls scrollIntoView if made active', () => {
+ createComponent({
+ file: {
+ ...file(),
+ type: 'blob',
+ active: false,
+ },
+ level: 0,
+ });
+
+ jest.spyOn(wrapper.vm, 'scrollIntoView');
+
+ wrapper.setProps({
+ file: Object.assign({}, wrapper.props('file'), {
+ active: true,
+ }),
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.scrollIntoView).toHaveBeenCalled();
+ });
+ });
+
+ it('indents row based on level', () => {
+ createComponent({
+ file: file('t4'),
+ level: 2,
+ });
+
+ expect(wrapper.find('.file-row-name').element.style.marginLeft).toBe('32px');
+ });
+
+ it('renders header for file', () => {
+ createComponent({
+ file: {
+ isHeader: true,
+ path: 'app/assets',
+ tree: [],
+ },
+ level: 0,
+ });
+
+ expect(wrapper.element.classList).toContain('js-file-row-header');
+ });
+});
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index a9f4b03eba5..dec7d6b2df3 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -27,7 +27,7 @@ describe BlobHelper do
end
describe "#edit_blob_link" do
- let(:namespace) { create(:namespace, name: 'gitlab' )}
+ let(:namespace) { create(:namespace, name: 'gitlab') }
let(:project) { create(:project, :repository, namespace: namespace) }
before do
@@ -202,6 +202,90 @@ describe BlobHelper do
end
end
end
+
+ describe '#show_suggest_pipeline_creation_celebration?' do
+ let(:blob) { fake_blob(path: Gitlab::FileDetector::PATTERNS[:gitlab_ci]) }
+ let(:current_user) { create(:user) }
+
+ before do
+ assign(:project, project)
+ assign(:blob, blob)
+ assign(:commit, double('Commit', sha: 'whatever'))
+ helper.request.cookies["suggest_gitlab_ci_yml_commit_#{project.id}"] = 'true'
+ allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: true))
+ allow(helper).to receive(:current_user).and_return(current_user)
+ end
+
+ context 'experiment enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).and_return(true)
+ end
+
+ it 'is true' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_truthy
+ end
+
+ context 'file is invalid format' do
+ before do
+ allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: false))
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
+
+ context 'path is not a ci file' do
+ before do
+ allow(blob).to receive(:path).and_return('something_bad')
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
+
+ context 'does not use the default ci config' do
+ before do
+ project.ci_config_path = 'something_bad'
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
+
+ context 'does not have the needed cookie' do
+ before do
+ helper.request.cookies.delete "suggest_gitlab_ci_yml_commit_#{project.id}"
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
+ end
+
+ context 'experiment disabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).and_return(false)
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
+ end
+ end
+
+ describe 'suggest_pipeline_commit_cookie_name' do
+ let(:project) { create(:project) }
+
+ it 'uses project id to make up the cookie name' do
+ assign(:project, project)
+
+ expect(helper.suggest_pipeline_commit_cookie_name).to eq "suggest_gitlab_ci_yml_commit_#{project.id}"
+ end
end
describe '#ide_edit_path' do
diff --git a/spec/javascripts/helpers/tracking_helper.js b/spec/javascripts/helpers/tracking_helper.js
index 68c1bd2dbca..bd3bd24028c 100644
--- a/spec/javascripts/helpers/tracking_helper.js
+++ b/spec/javascripts/helpers/tracking_helper.js
@@ -8,7 +8,7 @@ let handlers;
export function mockTracking(category = '_category_', documentOverride, spyMethod) {
document = documentOverride || window.document;
window.snowplow = () => {};
- Tracking.bindDocument(category, document);
+ handlers = Tracking.bindDocument(category, document);
return spyMethod ? spyMethod(Tracking, 'event') : null;
}
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index 2eaba46cdce..048a5f88c99 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -28,6 +28,7 @@ export default {
},
merge_status: 'can_be_merged',
merge_user_id: null,
+ pipelines_empty_svg_path: '/path/to/svg',
source_branch: 'daaaa',
source_branch_link: 'daaaa',
source_project_id: 19,
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
index 272f6cad5fc..796235be4c3 100644
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -96,5 +96,11 @@ describe('MergeRequestStore', () => {
expect(store.humanAccess).toEqual('Maintainer');
});
+
+ it('should set pipelinesEmptySvgPath', () => {
+ store.setData({ ...mockData });
+
+ expect(store.pipelinesEmptySvgPath).toBe('/path/to/svg');
+ });
});
});
diff --git a/spec/javascripts/vue_shared/components/file_row_spec.js b/spec/javascripts/vue_shared/components/file_row_spec.js
deleted file mode 100644
index 11fcb9b89c1..00000000000
--- a/spec/javascripts/vue_shared/components/file_row_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import Vue from 'vue';
-import { file } from 'spec/ide/helpers';
-import FileRow from '~/vue_shared/components/file_row.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('File row component', () => {
- let vm;
-
- function createComponent(propsData) {
- const FileRowComponent = Vue.extend(FileRow);
-
- vm = mountComponent(FileRowComponent, propsData);
- }
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders name', () => {
- createComponent({
- file: file('t4'),
- level: 0,
- });
-
- const name = vm.$el.querySelector('.file-row-name');
-
- expect(name.textContent.trim()).toEqual(vm.file.name);
- });
-
- it('emits toggleTreeOpen on click', () => {
- createComponent({
- file: {
- ...file('t3'),
- type: 'tree',
- },
- level: 0,
- });
- spyOn(vm, '$emit').and.stub();
-
- vm.$el.click();
-
- expect(vm.$emit).toHaveBeenCalledWith('toggleTreeOpen', vm.file.path);
- });
-
- it('calls scrollIntoView if made active', done => {
- createComponent({
- file: {
- ...file(),
- type: 'blob',
- active: false,
- },
- level: 0,
- });
-
- spyOn(vm, 'scrollIntoView').and.stub();
-
- vm.file.active = true;
-
- vm.$nextTick(() => {
- expect(vm.scrollIntoView).toHaveBeenCalled();
-
- done();
- });
- });
-
- it('indents row based on level', () => {
- createComponent({
- file: file('t4'),
- level: 2,
- });
-
- expect(vm.$el.querySelector('.file-row-name').style.marginLeft).toBe('32px');
- });
-
- it('renders header for file', () => {
- createComponent({
- file: {
- isHeader: true,
- path: 'app/assets',
- tree: [],
- },
- level: 0,
- });
-
- expect(vm.$el.classList).toContain('js-file-row-header');
- });
-});
diff --git a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
index b1d56b57596..9d8cd729958 100644
--- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
@@ -19,12 +19,14 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do
context 'with a metrics charts placeholder' do
let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) }
- it_behaves_like 'a supported metrics dashboard url'
+ it_behaves_like 'redacts the embed placeholder'
+ it_behaves_like 'retains the embed placeholder when applicable'
context 'for a grafana dashboard' do
let(:url) { urls.project_grafana_api_metrics_dashboard_url(project, embedded: true) }
- it_behaves_like 'a supported metrics dashboard url'
+ it_behaves_like 'redacts the embed placeholder'
+ it_behaves_like 'retains the embed placeholder when applicable'
end
context 'the user has requisite permissions' do
diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb
index e2117ca45ee..7d81170687a 100644
--- a/spec/requests/api/version_spec.rb
+++ b/spec/requests/api/version_spec.rb
@@ -12,17 +12,55 @@ describe API::Version do
end
end
- context 'when authenticated' do
+ context 'when authenticated as user' do
let(:user) { create(:user) }
it 'returns the version information' do
get api('/version', user)
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['version']).to eq(Gitlab::VERSION)
- expect(json_response['revision']).to eq(Gitlab.revision)
+ expect_version
end
end
+
+ context 'when authenticated with token' do
+ let(:personal_access_token) { create(:personal_access_token, scopes: scopes) }
+
+ context 'with api scope' do
+ let(:scopes) { %i(api) }
+
+ it 'returns the version information' do
+ get api('/version', personal_access_token: personal_access_token)
+
+ expect_version
+ end
+ end
+
+ context 'with read_user scope' do
+ let(:scopes) { %i(read_user) }
+
+ it 'returns the version information' do
+ get api('/version', personal_access_token: personal_access_token)
+
+ expect_version
+ end
+ end
+
+ context 'with neither api nor read_user scope' do
+ let(:scopes) { %i(read_repository) }
+
+ it 'returns authorization error' do
+ get api('/version', personal_access_token: personal_access_token)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
+
+ def expect_version
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['version']).to eq(Gitlab::VERSION)
+ expect(json_response['revision']).to eq(Gitlab.revision)
+ end
end
context 'with graphql enabled' do
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index f621cb650f9..597dae81cfb 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -75,8 +75,9 @@ describe MergeRequestWidgetEntity do
let(:role) { :developer }
it 'has add ci config path' do
- expect(subject[:merge_request_add_ci_config_path])
- .to eq("/#{resource.project.full_path}/-/new/#{resource.source_branch}?commit_message=Add+.gitlab-ci.yml&file_name=.gitlab-ci.yml")
+ expected_path = "/#{resource.project.full_path}/-/new/#{resource.source_branch}?commit_message=Add+.gitlab-ci.yml&file_name=.gitlab-ci.yml&suggest_gitlab_ci_yml=true"
+
+ expect(subject[:merge_request_add_ci_config_path]).to eq(expected_path)
end
context 'when source project is missing' do
diff --git a/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb b/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb
index d283b3a3b27..07abb86ceb5 100644
--- a/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb
+++ b/spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'a supported metrics dashboard url' do
+RSpec.shared_examples 'redacts the embed placeholder' do
context 'no user is logged in' do
it 'redacts the placeholder' do
expect(doc.to_s).to be_empty
@@ -14,7 +14,9 @@ RSpec.shared_examples 'a supported metrics dashboard url' do
expect(doc.to_s).to be_empty
end
end
+end
+RSpec.shared_examples 'retains the embed placeholder when applicable' do
context 'the user has requisite permissions' do
let(:user) { create(:user) }
let(:doc) { filter(input, current_user: user) }
@@ -22,7 +24,7 @@ RSpec.shared_examples 'a supported metrics dashboard url' do
it 'leaves the placeholder' do
project.add_maintainer(user)
- expect(doc.to_s).to eq(input)
+ expect(CGI.unescapeHTML(doc.to_s)).to eq(input)
end
end
end
diff --git a/spec/uploaders/import_export_uploader_spec.rb b/spec/uploaders/import_export_uploader_spec.rb
index 7e8937ff5a6..33cab911f86 100644
--- a/spec/uploaders/import_export_uploader_spec.rb
+++ b/spec/uploaders/import_export_uploader_spec.rb
@@ -51,4 +51,10 @@ describe ImportExportUploader do
end
end
end
+
+ describe '.workhorse_local_upload_path' do
+ it 'returns path that includes uploads dir' do
+ expect(described_class.workhorse_local_upload_path).to end_with('/uploads/tmp/uploads')
+ end
+ end
end