diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-05 00:07:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-05 00:07:50 +0000 |
commit | 54cbcea92909e69248abc9e6b92c7d14db3308a5 (patch) | |
tree | 1276f1c57b5ab1064db7197c2d28a8837d68d02d /spec | |
parent | 71221554dd9ddf30f73035c89f78164e001aa96d (diff) | |
download | gitlab-ce-54cbcea92909e69248abc9e6b92c7d14db3308a5.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/frontend/releases/list/components/release_block_milestone_info_spec.js | 179 | ||||
-rw-r--r-- | spec/frontend/releases/list/components/release_block_spec.js | 88 | ||||
-rw-r--r-- | spec/frontend/releases/mock_data.js | 8 | ||||
-rw-r--r-- | spec/lib/gitlab/throttle_spec.rb | 87 | ||||
-rw-r--r-- | spec/requests/rack_attack_global_spec.rb | 12 |
5 files changed, 327 insertions, 47 deletions
diff --git a/spec/frontend/releases/list/components/release_block_milestone_info_spec.js b/spec/frontend/releases/list/components/release_block_milestone_info_spec.js new file mode 100644 index 00000000000..c7d1bc3c372 --- /dev/null +++ b/spec/frontend/releases/list/components/release_block_milestone_info_spec.js @@ -0,0 +1,179 @@ +import { mount } from '@vue/test-utils'; +import { GlProgressBar, GlLink, GlBadge, GlButton } from '@gitlab/ui'; +import ReleaseBlockMilestoneInfo from '~/releases/list/components/release_block_milestone_info.vue'; +import { milestones } from '../../mock_data'; +import { trimText } from 'helpers/text_helper'; +import { MAX_MILESTONES_TO_DISPLAY } from '~/releases/list/constants'; + +describe('Release block milestone info', () => { + let wrapper; + let milestonesClone; + + const factory = milestonesProp => { + wrapper = mount(ReleaseBlockMilestoneInfo, { + propsData: { + milestones: milestonesProp, + }, + sync: false, + }); + + return wrapper.vm.$nextTick(); + }; + + beforeEach(() => { + milestonesClone = JSON.parse(JSON.stringify(milestones)); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + const milestoneProgressBarContainer = () => wrapper.find('.js-milestone-progress-bar-container'); + const milestoneListContainer = () => wrapper.find('.js-milestone-list-container'); + const issuesContainer = () => wrapper.find('.js-issues-container'); + + describe('with default props', () => { + beforeEach(() => factory(milestonesClone)); + + it('renders the correct percentage', () => { + expect(milestoneProgressBarContainer().text()).toContain('41% complete'); + }); + + it('renders a progress bar that displays the correct percentage', () => { + const progressBar = milestoneProgressBarContainer().find(GlProgressBar); + + expect(progressBar.exists()).toBe(true); + expect(progressBar.attributes()).toEqual( + expect.objectContaining({ + value: '22', + max: '54', + }), + ); + }); + + it('renders a list of links to all associated milestones', () => { + expect(trimText(milestoneListContainer().text())).toContain('Milestones 13.6 • 13.5'); + + milestonesClone.forEach((m, i) => { + const milestoneLink = milestoneListContainer() + .findAll(GlLink) + .at(i); + + expect(milestoneLink.text()).toBe(m.title); + expect(milestoneLink.attributes('href')).toBe(m.web_url); + expect(milestoneLink.attributes('data-original-title')).toBe(m.description); + }); + }); + + it('renders the "Issues" section with a total count of issues associated to the milestone(s)', () => { + const totalIssueCount = 54; + const issuesContainerText = trimText(issuesContainer().text()); + + expect(issuesContainerText).toContain(`Issues ${totalIssueCount}`); + + const badge = issuesContainer().find(GlBadge); + expect(badge.text()).toBe(totalIssueCount.toString()); + + expect(issuesContainerText).toContain('Open: 32 • Closed: 22'); + }); + }); + + describe('with lots of milestones', () => { + let lotsOfMilestones; + let fullListString; + let abbreviatedListString; + + beforeEach(() => { + lotsOfMilestones = []; + const template = milestonesClone[0]; + + for (let i = 0; i < MAX_MILESTONES_TO_DISPLAY + 10; i += 1) { + lotsOfMilestones.push({ + ...template, + id: template.id + i, + iid: template.iid + i, + title: `m-${i}`, + }); + } + + fullListString = lotsOfMilestones.map(m => m.title).join(' • '); + abbreviatedListString = lotsOfMilestones + .slice(0, MAX_MILESTONES_TO_DISPLAY) + .map(m => m.title) + .join(' • '); + + return factory(lotsOfMilestones); + }); + + const clickShowMoreFewerButton = () => { + milestoneListContainer() + .find(GlButton) + .trigger('click'); + + return wrapper.vm.$nextTick(); + }; + + const milestoneListText = () => trimText(milestoneListContainer().text()); + + it('only renders a subset of the milestones', () => { + expect(milestoneListText()).toContain(`Milestones ${abbreviatedListString} • show 10 more`); + }); + + it('renders all milestones when "show more" is clicked', () => + clickShowMoreFewerButton().then(() => { + expect(milestoneListText()).toContain(`Milestones ${fullListString} • show fewer`); + })); + + it('returns to the original view when "show fewer" is clicked', () => + clickShowMoreFewerButton() + .then(clickShowMoreFewerButton) + .then(() => { + expect(milestoneListText()).toContain( + `Milestones ${abbreviatedListString} • show 10 more`, + ); + })); + }); + + const expectAllZeros = () => { + it('displays percentage as 0%', () => { + expect(milestoneProgressBarContainer().text()).toContain('0% complete'); + }); + + it('shows 0 for all issue counts', () => { + const issuesContainerText = trimText(issuesContainer().text()); + + expect(issuesContainerText).toContain('Issues 0 Open: 0 • Closed: 0'); + }); + }; + + /** Ensures we don't have any issues with dividing by zero when computing percentages */ + describe('when all issue counts are zero', () => { + beforeEach(() => { + milestonesClone = milestonesClone.map(m => ({ + ...m, + issue_stats: { + ...m.issue_stats, + opened: 0, + closed: 0, + }, + })); + + return factory(milestonesClone); + }); + + expectAllZeros(); + }); + + describe('if the API response is missing the "issue_stats" property', () => { + beforeEach(() => { + milestonesClone = milestonesClone.map(m => ({ + ...m, + issue_stats: undefined, + })); + + return factory(milestonesClone); + }); + + expectAllZeros(); + }); +}); diff --git a/spec/frontend/releases/list/components/release_block_spec.js b/spec/frontend/releases/list/components/release_block_spec.js index 056835bdaf2..c7a1cbdea17 100644 --- a/spec/frontend/releases/list/components/release_block_spec.js +++ b/spec/frontend/releases/list/components/release_block_spec.js @@ -117,35 +117,6 @@ describe('Release block', () => { }); }); - it('renders the milestone icon', () => { - expect( - milestoneListLabel() - .find(Icon) - .exists(), - ).toBe(true); - }); - - it('renders the label as "Milestones" if more than one milestone is passed in', () => { - expect( - milestoneListLabel() - .find('.js-label-text') - .text(), - ).toEqual('Milestones'); - }); - - it('renders a link to the milestone with a tooltip', () => { - const milestone = first(release.milestones); - const milestoneLink = wrapper.find('.js-milestone-link'); - - expect(milestoneLink.exists()).toBe(true); - - expect(milestoneLink.text()).toBe(milestone.title); - - expect(milestoneLink.attributes('href')).toBe(milestone.web_url); - - expect(milestoneLink.attributes('data-original-title')).toBe(milestone.description); - }); - it('renders the footer', () => { expect(wrapper.find(ReleaseBlockFooter).exists()).toBe(true); }); @@ -187,18 +158,6 @@ describe('Release block', () => { }); }); - it('renders the label as "Milestone" if only a single milestone is passed in', () => { - releaseClone.milestones = releaseClone.milestones.slice(0, 1); - - return factory(releaseClone).then(() => { - expect( - milestoneListLabel() - .find('.js-label-text') - .text(), - ).toEqual('Milestone'); - }); - }); - it('renders upcoming release badge', () => { releaseClone.upcoming_release = true; @@ -281,4 +240,51 @@ describe('Release block', () => { }); }); }); + + describe('when the releaseIssueSummary feature flag is disabled', () => { + describe('with default props', () => { + beforeEach(() => factory(release, { releaseIssueSummary: false })); + + it('renders the milestone icon', () => { + expect( + milestoneListLabel() + .find(Icon) + .exists(), + ).toBe(true); + }); + + it('renders the label as "Milestones" if more than one milestone is passed in', () => { + expect( + milestoneListLabel() + .find('.js-label-text') + .text(), + ).toEqual('Milestones'); + }); + + it('renders a link to the milestone with a tooltip', () => { + const milestone = first(release.milestones); + const milestoneLink = wrapper.find('.js-milestone-link'); + + expect(milestoneLink.exists()).toBe(true); + + expect(milestoneLink.text()).toBe(milestone.title); + + expect(milestoneLink.attributes('href')).toBe(milestone.web_url); + + expect(milestoneLink.attributes('data-original-title')).toBe(milestone.description); + }); + }); + + it('renders the label as "Milestone" if only a single milestone is passed in', () => { + releaseClone.milestones = releaseClone.milestones.slice(0, 1); + + return factory(releaseClone, { releaseIssueSummary: false }).then(() => { + expect( + milestoneListLabel() + .find('.js-label-text') + .text(), + ).toEqual('Milestone'); + }); + }); + }); }); diff --git a/spec/frontend/releases/mock_data.js b/spec/frontend/releases/mock_data.js index e1830b494bc..630f14d3a73 100644 --- a/spec/frontend/releases/mock_data.js +++ b/spec/frontend/releases/mock_data.js @@ -11,6 +11,10 @@ export const milestones = [ due_date: '2019-09-19', start_date: '2019-08-31', web_url: 'http://0.0.0.0:3001/root/release-test/-/milestones/2', + issue_stats: { + opened: 14, + closed: 19, + }, }, { id: 49, @@ -24,6 +28,10 @@ export const milestones = [ due_date: '2019-10-11', start_date: '2019-08-19', web_url: 'http://0.0.0.0:3001/root/release-test/-/milestones/1', + issue_stats: { + opened: 18, + closed: 3, + }, }, ]; diff --git a/spec/lib/gitlab/throttle_spec.rb b/spec/lib/gitlab/throttle_spec.rb new file mode 100644 index 00000000000..674646a5f06 --- /dev/null +++ b/spec/lib/gitlab/throttle_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Throttle do + describe '.protected_paths_enabled?' do + subject { described_class.protected_paths_enabled? } + + context 'when omnibus protected paths throttle should be used' do + before do + expect(described_class).to receive(:should_use_omnibus_protected_paths?).and_return(true) + end + + it { is_expected.to be_falsey } + end + + context 'when omnibus protected paths throttle should not be used' do + before do + expect(described_class).to receive(:should_use_omnibus_protected_paths?).and_return(false) + end + + it 'returns Application Settings throttle_protected_paths_enabled?' do + expect(Gitlab::CurrentSettings.current_application_settings).to receive(:throttle_protected_paths_enabled?) + + subject + end + end + end + + describe '.should_use_omnibus_protected_paths?' do + subject { described_class.should_use_omnibus_protected_paths? } + + context 'when rack_attack.admin_area_protected_paths_enabled config is unspecified' do + context 'when the omnibus protected paths throttle has been recently used (it has data)' do + before do + expect(described_class).to receive(:omnibus_protected_paths_present?).and_return(true) + end + + it { is_expected.to be_truthy } + end + + context 'when the omnibus protected paths throttle has not been recently used' do + before do + expect(described_class).to receive(:omnibus_protected_paths_present?).and_return(false) + end + + it { is_expected.to be_falsey } + end + end + + context 'when rack_attack.admin_area_protected_paths_enabled config is false' do + before do + stub_config(rack_attack: { + admin_area_protected_paths_enabled: false + }) + end + + context 'when the omnibus protected paths throttle has been recently used (it has data)' do + before do + expect(described_class).to receive(:omnibus_protected_paths_present?).and_return(true) + end + + it { is_expected.to be_truthy } + end + + context 'when the omnibus protected paths throttle has not been recently used' do + before do + expect(described_class).to receive(:omnibus_protected_paths_present?).and_return(false) + end + + it { is_expected.to be_falsey } + end + end + + context 'when rack_attack.admin_area_protected_paths_enabled config is true' do + before do + stub_config(rack_attack: { + admin_area_protected_paths_enabled: true + }) + + expect(described_class).not_to receive(:omnibus_protected_paths_present?) + end + + it { is_expected.to be_falsey } + end + end +end diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb index 4d5055a7e27..59113687d1c 100644 --- a/spec/requests/rack_attack_global_spec.rb +++ b/spec/requests/rack_attack_global_spec.rb @@ -249,10 +249,10 @@ describe 'Rack Attack global throttles' do expect_rejection { post protected_path_that_does_not_require_authentication, params: post_params } end - context 'when Omnibus throttle is present' do + context 'when Omnibus throttle should be used' do before do allow(Gitlab::Throttle) - .to receive(:omnibus_protected_paths_present?).and_return(true) + .to receive(:should_use_omnibus_protected_paths?).and_return(true) end it 'allows requests over the rate limit' do @@ -298,7 +298,7 @@ describe 'Rack Attack global throttles' do it_behaves_like 'rate-limited token-authenticated requests' end - context 'when Omnibus throttle is present' do + context 'when Omnibus throttle should be used' do let(:request_args) { [api(api_partial_url, personal_access_token: token)] } let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] } @@ -309,7 +309,7 @@ describe 'Rack Attack global throttles' do stub_application_setting(settings_to_set) allow(Gitlab::Throttle) - .to receive(:omnibus_protected_paths_present?).and_return(true) + .to receive(:should_use_omnibus_protected_paths?).and_return(true) end it 'allows requests over the rate limit' do @@ -339,7 +339,7 @@ describe 'Rack Attack global throttles' do it_behaves_like 'rate-limited web authenticated requests' - context 'when Omnibus throttle is present' do + context 'when Omnibus throttle should be used' do before do settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds @@ -347,7 +347,7 @@ describe 'Rack Attack global throttles' do stub_application_setting(settings_to_set) allow(Gitlab::Throttle) - .to receive(:omnibus_protected_paths_present?).and_return(true) + .to receive(:should_use_omnibus_protected_paths?).and_return(true) login_as(user) end |