diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-05 15:08:48 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-05 15:08:48 +0000 |
commit | eabf8fd774fef6a54903e5141138f47bdafeb331 (patch) | |
tree | c74ff99fa6765cbe091767e9827374ce44b0df50 /spec | |
parent | 20d564f1064622ef0623434372ac3ceb03173331 (diff) | |
download | gitlab-ce-eabf8fd774fef6a54903e5141138f47bdafeb331.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/frontend/environments/environment_actions_spec.js | 124 | ||||
-rw-r--r-- | spec/frontend/repository/router_spec.js | 1 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_actions_spec.js | 117 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/bar_chart_spec.js | 79 | ||||
-rw-r--r-- | spec/lib/quality/test_level_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/sentry_issue_spec.rb | 29 |
6 files changed, 150 insertions, 204 deletions
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js new file mode 100644 index 00000000000..4c06e19cec0 --- /dev/null +++ b/spec/frontend/environments/environment_actions_spec.js @@ -0,0 +1,124 @@ +import { shallowMount } from '@vue/test-utils'; +import { TEST_HOST } from 'helpers/test_constants'; +import eventHub from '~/environments/event_hub'; +import EnvironmentActions from '~/environments/components/environment_actions.vue'; +import Icon from '~/vue_shared/components/icon.vue'; +import { GlLoadingIcon } from '@gitlab/ui'; + +describe('EnvironmentActions Component', () => { + let vm; + + beforeEach(() => { + vm = shallowMount(EnvironmentActions, { propsData: { actions: [] } }); + }); + + afterEach(() => { + vm.destroy(); + }); + + it('should render a dropdown button with 2 icons', () => { + expect(vm.find('.dropdown-new').findAll(Icon).length).toBe(2); + }); + + it('should render a dropdown button with aria-label description', () => { + expect(vm.find('.dropdown-new').attributes('aria-label')).toEqual('Deploy to...'); + }); + + describe('is loading', () => { + beforeEach(() => { + vm.setData({ isLoading: true }); + }); + + it('should render a dropdown button with a loading icon', () => { + expect(vm.findAll(GlLoadingIcon).length).toBe(1); + }); + }); + + describe('manual actions', () => { + const actions = [ + { + name: 'bar', + play_path: 'https://gitlab.com/play', + }, + { + name: 'foo', + play_path: '#', + }, + { + name: 'foo bar', + play_path: 'url', + playable: false, + }, + ]; + + beforeEach(() => { + vm.setProps({ actions }); + }); + + it('should render a dropdown with the provided list of actions', () => { + expect(vm.findAll('.dropdown-menu li').length).toEqual(actions.length); + }); + + it("should render a disabled action when it's not playable", () => { + expect(vm.find('.dropdown-menu li:last-child button').attributes('disabled')).toEqual( + 'disabled', + ); + + expect(vm.find('.dropdown-menu li:last-child button').classes('disabled')).toBe(true); + }); + }); + + describe('scheduled jobs', () => { + const scheduledJobAction = { + name: 'scheduled action', + playPath: `${TEST_HOST}/scheduled/job/action`, + playable: true, + scheduledAt: '2063-04-05T00:42:00Z', + }; + const expiredJobAction = { + name: 'expired action', + playPath: `${TEST_HOST}/expired/job/action`, + playable: true, + scheduledAt: '2018-10-05T08:23:00Z', + }; + const findDropdownItem = action => { + const buttons = vm.findAll('.dropdown-menu li button'); + return buttons.filter(button => button.text().startsWith(action.name)).at(0); + }; + + beforeEach(() => { + jest.spyOn(Date, 'now').mockImplementation(() => new Date('2063-04-04T00:42:00Z').getTime()); + vm.setProps({ actions: [scheduledJobAction, expiredJobAction] }); + }); + + it('emits postAction event after confirming', () => { + const emitSpy = jest.fn(); + eventHub.$on('postAction', emitSpy); + jest.spyOn(window, 'confirm').mockImplementation(() => true); + + findDropdownItem(scheduledJobAction).trigger('click'); + + expect(window.confirm).toHaveBeenCalled(); + expect(emitSpy).toHaveBeenCalledWith({ endpoint: scheduledJobAction.playPath }); + }); + + it('does not emit postAction event if confirmation is cancelled', () => { + const emitSpy = jest.fn(); + eventHub.$on('postAction', emitSpy); + jest.spyOn(window, 'confirm').mockImplementation(() => false); + + findDropdownItem(scheduledJobAction).trigger('click'); + + expect(window.confirm).toHaveBeenCalled(); + expect(emitSpy).not.toHaveBeenCalled(); + }); + + it('displays the remaining time in the dropdown', () => { + expect(findDropdownItem(scheduledJobAction).text()).toContain('24:00:00'); + }); + + it('displays 00:00:00 for expired jobs in the dropdown', () => { + expect(findDropdownItem(expiredJobAction).text()).toContain('00:00:00'); + }); + }); +}); diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js index 1efd74a30c2..8f3ac53c37a 100644 --- a/spec/frontend/repository/router_spec.js +++ b/spec/frontend/repository/router_spec.js @@ -6,6 +6,7 @@ describe('Repository router spec', () => { it.each` path | component | componentName ${'/'} | ${IndexPage} | ${'IndexPage'} + ${'/tree/master'} | ${TreePage} | ${'TreePage'} ${'/-/tree/master'} | ${TreePage} | ${'TreePage'} ${'/-/tree/master/app/assets'} | ${TreePage} | ${'TreePage'} ${'/-/tree/123/app/assets'} | ${null} | ${'null'} diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js deleted file mode 100644 index a844660f7bf..00000000000 --- a/spec/javascripts/environments/environment_actions_spec.js +++ /dev/null @@ -1,117 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import { TEST_HOST } from 'spec/test_constants'; -import eventHub from '~/environments/event_hub'; -import EnvironmentActions from '~/environments/components/environment_actions.vue'; - -describe('EnvironmentActions Component', () => { - const Component = Vue.extend(EnvironmentActions); - let vm; - - afterEach(() => { - vm.$destroy(); - }); - - describe('manual actions', () => { - const actions = [ - { - name: 'bar', - play_path: 'https://gitlab.com/play', - }, - { - name: 'foo', - play_path: '#', - }, - { - name: 'foo bar', - play_path: 'url', - playable: false, - }, - ]; - - beforeEach(() => { - vm = mountComponent(Component, { actions }); - }); - - it('should render a dropdown button with icon and title attribute', () => { - expect(vm.$el.querySelector('.fa-caret-down')).toBeDefined(); - expect(vm.$el.querySelector('.dropdown-new').getAttribute('data-original-title')).toEqual( - 'Deploy to...', - ); - - expect(vm.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual( - 'Deploy to...', - ); - }); - - it('should render a dropdown with the provided list of actions', () => { - expect(vm.$el.querySelectorAll('.dropdown-menu li').length).toEqual(actions.length); - }); - - it("should render a disabled action when it's not playable", () => { - expect( - vm.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'), - ).toEqual('disabled'); - - expect( - vm.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'), - ).toEqual(true); - }); - }); - - describe('scheduled jobs', () => { - const scheduledJobAction = { - name: 'scheduled action', - playPath: `${TEST_HOST}/scheduled/job/action`, - playable: true, - scheduledAt: '2063-04-05T00:42:00Z', - }; - const expiredJobAction = { - name: 'expired action', - playPath: `${TEST_HOST}/expired/job/action`, - playable: true, - scheduledAt: '2018-10-05T08:23:00Z', - }; - const findDropdownItem = action => { - const buttons = vm.$el.querySelectorAll('.dropdown-menu li button'); - return Array.prototype.find.call(buttons, element => - element.innerText.trim().startsWith(action.name), - ); - }; - - beforeEach(() => { - spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime()); - vm = mountComponent(Component, { actions: [scheduledJobAction, expiredJobAction] }); - }); - - it('emits postAction event after confirming', () => { - const emitSpy = jasmine.createSpy('emit'); - eventHub.$on('postAction', emitSpy); - spyOn(window, 'confirm').and.callFake(() => true); - - findDropdownItem(scheduledJobAction).click(); - - expect(window.confirm).toHaveBeenCalled(); - expect(emitSpy).toHaveBeenCalledWith({ endpoint: scheduledJobAction.playPath }); - }); - - it('does not emit postAction event if confirmation is cancelled', () => { - const emitSpy = jasmine.createSpy('emit'); - eventHub.$on('postAction', emitSpy); - spyOn(window, 'confirm').and.callFake(() => false); - - findDropdownItem(scheduledJobAction).click(); - - expect(window.confirm).toHaveBeenCalled(); - expect(emitSpy).not.toHaveBeenCalled(); - }); - - it('displays the remaining time in the dropdown', () => { - expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00'); - }); - - it('displays 00:00:00 for expired jobs in the dropdown', () => { - expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00'); - }); - }); -}); diff --git a/spec/javascripts/vue_shared/components/bar_chart_spec.js b/spec/javascripts/vue_shared/components/bar_chart_spec.js deleted file mode 100644 index 8f673c146ec..00000000000 --- a/spec/javascripts/vue_shared/components/bar_chart_spec.js +++ /dev/null @@ -1,79 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import BarChart from '~/vue_shared/components/bar_chart.vue'; - -function getRandomArbitrary(min, max) { - return Math.random() * (max - min) + min; -} - -function generateRandomData(dataNumber) { - const randomGraphData = []; - - for (let i = 1; i <= dataNumber; i += 1) { - randomGraphData.push({ - name: `random ${i}`, - value: parseInt(getRandomArbitrary(1, 8), 10), - }); - } - - return randomGraphData; -} - -describe('Bar chart component', () => { - let barChart; - const graphData = generateRandomData(10); - - beforeEach(() => { - const BarChartComponent = Vue.extend(BarChart); - - barChart = mountComponent(BarChartComponent, { - graphData, - yAxisLabel: 'data', - }); - }); - - afterEach(() => { - barChart.$destroy(); - }); - - it('calculates the padding for even distribution across bars', () => { - barChart.vbWidth = 1000; - const result = barChart.calculatePadding(30); - - // since padding can't be higher than 1 and lower than 0 - // for more info: https://github.com/d3/d3-scale#band-scales - expect(result).not.toBeLessThan(0); - expect(result).not.toBeGreaterThan(1); - }); - - it('formats the tooltip title', () => { - const tooltipTitle = barChart.setTooltipTitle(barChart.graphData[0]); - - expect(tooltipTitle).toContain('random 1:'); - }); - - it('has a translates the bar graphs on across the X axis', () => { - barChart.panX = 100; - - expect(barChart.barTranslationTransform).toEqual('translate(100, 0)'); - }); - - it('translates the scroll indicator to the far right side', () => { - barChart.vbWidth = 500; - - expect(barChart.scrollIndicatorTransform).toEqual('translate(420, 0)'); - }); - - it('translates the x-axis to the bottom of the viewbox and pan coordinates', () => { - barChart.panX = 100; - barChart.vbHeight = 250; - - expect(barChart.xAxisLocation).toEqual('translate(100, 250)'); - }); - - it('rotates the x axis labels a total of 90 degress (CCW)', () => { - const xAxisLabel = barChart.$el.querySelector('.x-axis').querySelectorAll('text')[0]; - - expect(xAxisLabel.getAttribute('transform')).toEqual('rotate(-90)'); - }); -}); diff --git a/spec/lib/quality/test_level_spec.rb b/spec/lib/quality/test_level_spec.rb index 621a426a18d..13817bdcc72 100644 --- a/spec/lib/quality/test_level_spec.rb +++ b/spec/lib/quality/test_level_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Quality::TestLevel do context 'when level is unit' do it 'returns a pattern' do expect(subject.pattern(:unit)) - .to eq("spec/{bin,config,db,dependencies,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,tasks,uploaders,validators,views,workers,elastic_integration}{,/**/}*_spec.rb") + .to eq("spec/{bin,config,db,dependencies,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,routing,rubocop,serializers,services,sidekiq,tasks,uploaders,validators,views,workers,elastic_integration}{,/**/}*_spec.rb") end end @@ -82,7 +82,7 @@ RSpec.describe Quality::TestLevel do context 'when level is unit' do it 'returns a regexp' do expect(subject.regexp(:unit)) - .to eq(%r{spec/(bin|config|db|dependencies|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|tasks|uploaders|validators|views|workers|elastic_integration)}) + .to eq(%r{spec/(bin|config|db|dependencies|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|routing|rubocop|serializers|services|sidekiq|tasks|uploaders|validators|views|workers|elastic_integration)}) end end diff --git a/spec/models/sentry_issue_spec.rb b/spec/models/sentry_issue_spec.rb index 022cfd4734e..b4c1cf57761 100644 --- a/spec/models/sentry_issue_spec.rb +++ b/spec/models/sentry_issue_spec.rb @@ -13,6 +13,20 @@ describe SentryIssue do it { is_expected.to validate_presence_of(:issue) } it { is_expected.to validate_uniqueness_of(:issue) } it { is_expected.to validate_presence_of(:sentry_issue_identifier) } + + it 'allows duplicated sentry_issue_identifier' do + duplicate_sentry_issue = build(:sentry_issue, sentry_issue_identifier: sentry_issue.sentry_issue_identifier) + + expect(duplicate_sentry_issue).to be_valid + end + + it 'validates uniqueness of sentry_issue_identifier per project' do + second_issue = create(:issue, project: sentry_issue.issue.project) + duplicate_sentry_issue = build(:sentry_issue, issue: second_issue, sentry_issue_identifier: sentry_issue.sentry_issue_identifier) + + expect(duplicate_sentry_issue).to be_invalid + expect(duplicate_sentry_issue.errors.full_messages.first).to include('is already associated') + end end describe 'callbacks' do @@ -28,13 +42,16 @@ describe SentryIssue do end describe '.for_project_and_identifier' do - let!(:sentry_issue) { create(:sentry_issue) } - let(:project) { sentry_issue.issue.project } - let(:identifier) { sentry_issue.sentry_issue_identifier } - let!(:second_sentry_issue) { create(:sentry_issue) } + it 'finds the most recent per project and sentry_issue_identifier' do + sentry_issue = create(:sentry_issue) + create(:sentry_issue) + project = sentry_issue.issue.project + sentry_issue_3 = build(:sentry_issue, issue: create(:issue, project: project), sentry_issue_identifier: sentry_issue.sentry_issue_identifier) + sentry_issue_3.save(validate: false) - subject { described_class.for_project_and_identifier(project, identifier) } + result = described_class.for_project_and_identifier(project, sentry_issue.sentry_issue_identifier) - it { is_expected.to eq(sentry_issue) } + expect(result).to eq(sentry_issue_3) + end end end |