diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/finders/jobs_finder_spec.rb | 89 | ||||
-rw-r--r-- | spec/frontend/vue_shared/components/markdown/field_spec.js | 179 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/markdown/field_spec.js | 173 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 49 |
4 files changed, 271 insertions, 219 deletions
diff --git a/spec/finders/jobs_finder_spec.rb b/spec/finders/jobs_finder_spec.rb new file mode 100644 index 00000000000..675d170b90e --- /dev/null +++ b/spec/finders/jobs_finder_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe JobsFinder, '#execute' do + set(:user) { create(:user) } + set(:admin) { create(:user, :admin) } + set(:project) { create(:project, :private, public_builds: false) } + set(:pipeline) { create(:ci_pipeline, project: project) } + set(:job_1) { create(:ci_build) } + set(:job_2) { create(:ci_build, :running) } + set(:job_3) { create(:ci_build, :success, pipeline: pipeline) } + + let(:params) { {} } + + context 'no project' do + subject { described_class.new(current_user: admin, params: params).execute } + + it 'returns all jobs' do + expect(subject).to match_array([job_1, job_2, job_3]) + end + + context 'non admin user' do + let(:admin) { user } + + it 'returns no jobs' do + expect(subject).to be_empty + end + end + + context 'without user' do + let(:admin) { nil } + + it 'returns no jobs' do + expect(subject).to be_empty + end + end + + context 'scope is present' do + let(:jobs) { [job_1, job_2, job_3] } + + where(:scope, :index) do + [ + ['pending', 0], + ['running', 1], + ['finished', 2] + ] + end + + with_them do + let(:params) { { scope: scope } } + + it { expect(subject).to match_array([jobs[index]]) } + end + end + end + + context 'a project is present' do + subject { described_class.new(current_user: user, project: project, params: params).execute } + + context 'user has access to the project' do + before do + project.add_maintainer(user) + end + + it 'returns jobs for the specified project' do + expect(subject).to match_array([job_3]) + end + end + + context 'user has no access to project builds' do + before do + project.add_guest(user) + end + + it 'returns no jobs' do + expect(subject).to be_empty + end + end + + context 'without user' do + let(:user) { nil } + + it 'returns no jobs' do + expect(subject).to be_empty + end + end + end +end diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js new file mode 100644 index 00000000000..b006f72b8ee --- /dev/null +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -0,0 +1,179 @@ +import { mount, createLocalVue } from '@vue/test-utils'; +import fieldComponent from '~/vue_shared/components/markdown/field.vue'; +import { TEST_HOST } from 'spec/test_constants'; +import AxiosMockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import $ from 'jquery'; + +const markdownPreviewPath = `${TEST_HOST}/preview`; +const markdownDocsPath = `${TEST_HOST}/docs`; + +function assertMarkdownTabs(isWrite, writeLink, previewLink, wrapper) { + expect(writeLink.element.parentNode.classList.contains('active')).toEqual(isWrite); + expect(previewLink.element.parentNode.classList.contains('active')).toEqual(!isWrite); + expect(wrapper.find('.md-preview-holder').element.style.display).toEqual(isWrite ? 'none' : ''); +} + +function createComponent() { + const wrapper = mount(fieldComponent, { + propsData: { + markdownDocsPath, + markdownPreviewPath, + }, + slots: { + textarea: '<textarea>testing\n123</textarea>', + }, + template: ` + <field-component + markdown-preview-path="${markdownPreviewPath}" + markdown-docs-path="${markdownDocsPath}" + > + <textarea + slot="textarea" + v-model="text"> + <slot>this is a test</slot> + </textarea> + </field-component> + `, + sync: false, + }); + return wrapper; +} + +const getPreviewLink = wrapper => wrapper.find('.nav-links .js-preview-link'); +const getWriteLink = wrapper => wrapper.find('.nav-links .js-write-link'); +const getMarkdownButton = wrapper => wrapper.find('.js-md'); +const getAllMarkdownButtons = wrapper => wrapper.findAll('.js-md'); + +describe('Markdown field component', () => { + let axiosMock; + const localVue = createLocalVue(); + + beforeEach(() => { + axiosMock = new AxiosMockAdapter(axios); + }); + + afterEach(() => { + axiosMock.restore(); + }); + + describe('mounted', () => { + let wrapper; + const previewHTML = '<p>markdown preview</p>'; + let previewLink; + let writeLink; + + it('renders textarea inside backdrop', () => { + wrapper = createComponent(); + expect(wrapper.find('.zen-backdrop textarea').element).not.toBeNull(); + }); + + describe('markdown preview', () => { + beforeEach(() => { + axiosMock.onPost(markdownPreviewPath).reply(200, { body: previewHTML }); + }); + + it('sets preview link as active', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + return localVue.nextTick().then(() => { + expect(previewLink.element.parentNode.classList.contains('active')).toBeTruthy(); + }); + }); + + it('shows preview loading text', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + localVue.nextTick(() => { + expect(wrapper.find('.md-preview-holder').element.textContent.trim()).toContain( + 'Loading…', + ); + }); + }); + + it('renders markdown preview', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + setTimeout(() => { + expect(wrapper.find('.md-preview-holder').element.innerHTML).toContain(previewHTML); + }); + }); + + it('renders GFM with jQuery', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + jest.spyOn($.fn, 'renderGFM'); + + previewLink.trigger('click'); + + setTimeout(() => { + expect($.fn.renderGFM).toHaveBeenCalled(); + }, 0); + }); + + it('clicking already active write or preview link does nothing', () => { + wrapper = createComponent(); + writeLink = getWriteLink(wrapper); + previewLink = getPreviewLink(wrapper); + + writeLink.trigger('click'); + return localVue + .nextTick() + .then(() => assertMarkdownTabs(true, writeLink, previewLink, wrapper)) + .then(() => writeLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(true, writeLink, previewLink, wrapper)) + .then(() => previewLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(false, writeLink, previewLink, wrapper)) + .then(() => previewLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(false, writeLink, previewLink, wrapper)); + }); + }); + + describe('markdown buttons', () => { + it('converts single words', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 7); + const markdownButton = getMarkdownButton(wrapper); + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('**testing**'); + }); + }); + + it('converts a line', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 0); + const markdownButton = getAllMarkdownButtons(wrapper).wrappers[5]; + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('* testing'); + }); + }); + + it('converts multiple lines', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 50); + const markdownButton = getAllMarkdownButtons(wrapper).wrappers[5]; + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('* testing\n* 123'); + }); + }); + }); + }); +}); diff --git a/spec/javascripts/vue_shared/components/markdown/field_spec.js b/spec/javascripts/vue_shared/components/markdown/field_spec.js deleted file mode 100644 index da984175f9f..00000000000 --- a/spec/javascripts/vue_shared/components/markdown/field_spec.js +++ /dev/null @@ -1,173 +0,0 @@ -import $ from 'jquery'; -import '~/behaviors/markdown/render_gfm'; -import Vue from 'vue'; -import AxiosMockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import fieldComponent from '~/vue_shared/components/markdown/field.vue'; -import { TEST_HOST } from 'spec/test_constants'; - -function assertMarkdownTabs(isWrite, writeLink, previewLink, vm) { - expect(writeLink.parentNode.classList.contains('active')).toEqual(isWrite); - expect(previewLink.parentNode.classList.contains('active')).toEqual(!isWrite); - expect(vm.$el.querySelector('.md-preview-holder').style.display).toEqual(isWrite ? 'none' : ''); -} - -describe('Markdown field component', () => { - const markdownPreviewPath = `${TEST_HOST}/preview`; - const markdownDocsPath = `${TEST_HOST}/docs`; - let axiosMock; - let vm; - - beforeEach(done => { - axiosMock = new AxiosMockAdapter(axios); - vm = new Vue({ - components: { - fieldComponent, - }, - data() { - return { - text: 'testing\n123', - }; - }, - template: ` - <field-component - markdown-preview-path="${markdownPreviewPath}" - markdown-docs-path="${markdownDocsPath}" - > - <textarea - slot="textarea" - v-model="text"> - </textarea> - </field-component> - `, - }).$mount(); - - Vue.nextTick(done); - }); - - afterEach(() => { - axiosMock.restore(); - }); - - describe('mounted', () => { - const previewHTML = '<p>markdown preview</p>'; - - it('renders textarea inside backdrop', () => { - expect(vm.$el.querySelector('.zen-backdrop textarea')).not.toBeNull(); - }); - - describe('markdown preview', () => { - let previewLink; - let writeLink; - - beforeEach(() => { - axiosMock.onPost(markdownPreviewPath).replyOnce(200, { body: previewHTML }); - - previewLink = vm.$el.querySelector('.nav-links .js-preview-link'); - writeLink = vm.$el.querySelector('.nav-links .js-write-link'); - }); - - it('sets preview link as active', done => { - previewLink.click(); - - Vue.nextTick(() => { - expect(previewLink.parentNode.classList.contains('active')).toBeTruthy(); - - done(); - }); - }); - - it('shows preview loading text', done => { - previewLink.click(); - - Vue.nextTick(() => { - expect(vm.$el.querySelector('.md-preview-holder').textContent.trim()).toContain( - 'Loading…', - ); - - done(); - }); - }); - - it('renders markdown preview', done => { - previewLink.click(); - - setTimeout(() => { - expect(vm.$el.querySelector('.md-preview-holder').innerHTML).toContain(previewHTML); - - done(); - }); - }); - - it('renders GFM with jQuery', done => { - spyOn($.fn, 'renderGFM'); - - previewLink.click(); - - setTimeout(() => { - expect($.fn.renderGFM).toHaveBeenCalled(); - - done(); - }, 0); - }); - - it('clicking already active write or preview link does nothing', done => { - writeLink.click(); - Vue.nextTick() - .then(() => assertMarkdownTabs(true, writeLink, previewLink, vm)) - .then(() => writeLink.click()) - .then(() => Vue.nextTick()) - .then(() => assertMarkdownTabs(true, writeLink, previewLink, vm)) - .then(() => previewLink.click()) - .then(() => Vue.nextTick()) - .then(() => assertMarkdownTabs(false, writeLink, previewLink, vm)) - .then(() => previewLink.click()) - .then(() => Vue.nextTick()) - .then(() => assertMarkdownTabs(false, writeLink, previewLink, vm)) - .then(done) - .catch(done.fail); - }); - }); - - describe('markdown buttons', () => { - it('converts single words', done => { - const textarea = vm.$el.querySelector('textarea'); - - textarea.setSelectionRange(0, 7); - vm.$el.querySelector('.js-md').click(); - - Vue.nextTick(() => { - expect(textarea.value).toContain('**testing**'); - - done(); - }); - }); - - it('converts a line', done => { - const textarea = vm.$el.querySelector('textarea'); - - textarea.setSelectionRange(0, 0); - vm.$el.querySelectorAll('.js-md')[5].click(); - - Vue.nextTick(() => { - expect(textarea.value).toContain('* testing'); - - done(); - }); - }); - - it('converts multiple lines', done => { - const textarea = vm.$el.querySelector('textarea'); - - textarea.setSelectionRange(0, 50); - vm.$el.querySelectorAll('.js-md')[5].click(); - - Vue.nextTick(() => { - expect(textarea.value).toContain('* testing\n* 123'); - - done(); - }); - }); - }); - }); -}); diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 977f1fdd267..d34919d17fe 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -199,25 +199,6 @@ describe Ci::Pipeline, :mailer do end end - describe '#merge_train_pipeline?' do - subject { pipeline.merge_train_pipeline? } - - let!(:pipeline) do - create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: ref, target_sha: 'xxx') - end - - let(:merge_request) { create(:merge_request) } - let(:ref) { 'refs/merge-requests/1/train' } - - it { is_expected.to be_truthy } - - context 'when ref is merge ref' do - let(:ref) { 'refs/merge-requests/1/merge' } - - it { is_expected.to be_falsy } - end - end - describe '#merge_request_ref?' do subject { pipeline.merge_request_ref? } @@ -228,43 +209,19 @@ describe Ci::Pipeline, :mailer do end end - describe '#merge_train_ref?' do - subject { pipeline.merge_train_ref? } - - it 'calls Mergetrain#merge_train_ref?' do - expect(MergeRequest).to receive(:merge_train_ref?).with(pipeline.ref) - - subject - end - end - describe '#merge_request_event_type' do subject { pipeline.merge_request_event_type } - before do - allow(pipeline).to receive(:merge_request_event?) { true } - end - - context 'when pipeline is merge train pipeline' do - before do - allow(pipeline).to receive(:merge_train_pipeline?) { true } - end - - it { is_expected.to eq(:merge_train) } - end + let(:pipeline) { merge_request.all_pipelines.last } context 'when pipeline is merge request pipeline' do - before do - allow(pipeline).to receive(:merge_request_pipeline?) { true } - end + let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } it { is_expected.to eq(:merged_result) } end context 'when pipeline is detached merge request pipeline' do - before do - allow(pipeline).to receive(:detached_merge_request_pipeline?) { true } - end + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } it { is_expected.to eq(:detached) } end |