diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-10 03:10:29 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-10 03:10:29 +0300 |
commit | 981771279a48c03263e29f3b4f41f54204ea3146 (patch) | |
tree | 5e48e8debb84850147d183b094ffcd9d8b084c48 /spec | |
parent | a8648ba08604085c76be1e4f5253ffa89aa192e3 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
4 files changed, 157 insertions, 49 deletions
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js index e77bae79f68..fb95be3a77c 100644 --- a/spec/frontend/snippets/components/snippet_header_spec.js +++ b/spec/frontend/snippets/components/snippet_header_spec.js @@ -1,4 +1,4 @@ -import { GlButton, GlModal } from '@gitlab/ui'; +import { GlButton, GlModal, GlDropdown } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { ApolloMutation } from 'vue-apollo'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; @@ -8,8 +8,6 @@ import { differenceInMilliseconds } from '~/lib/utils/datetime_utility'; import SnippetHeader from '~/snippets/components/snippet_header.vue'; import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql'; -useMockLocationHelper(); - describe('Snippet header component', () => { let wrapper; let snippet; @@ -19,6 +17,7 @@ describe('Snippet header component', () => { let errorMsg; let err; const originalRelativeUrlRoot = gon.relative_url_root; + const reportAbusePath = '/-/snippets/42/mark_as_spam'; const GlEmoji = { template: '<img/>' }; @@ -27,6 +26,7 @@ describe('Snippet header component', () => { permissions = {}, mutationRes = mutationTypes.RESOLVE, snippetProps = {}, + provide = {}, } = {}) { const defaultProps = Object.assign(snippet, snippetProps); if (permissions) { @@ -45,6 +45,10 @@ describe('Snippet header component', () => { wrapper = mount(SnippetHeader, { mocks: { $apollo }, + provide: { + reportAbusePath, + ...provide, + }, propsData: { snippet: { ...defaultProps, @@ -57,9 +61,27 @@ describe('Snippet header component', () => { }); } - const findAuthorEmoji = () => wrapper.find(GlEmoji); + const findAuthorEmoji = () => wrapper.findComponent(GlEmoji); const findAuthoredMessage = () => wrapper.find('[data-testid="authored-message"]').text(); - const buttonCount = () => wrapper.findAll(GlButton).length; + const findButtons = () => wrapper.findAllComponents(GlButton); + const findButtonsAsModel = () => + findButtons().wrappers.map((x) => ({ + text: x.text(), + href: x.attributes('href'), + category: x.props('category'), + variant: x.props('variant'), + disabled: x.props('disabled'), + })); + const findResponsiveDropdown = () => wrapper.findComponent(GlDropdown); + // We can't search by component here since we are full mounting and the attributes are applied to a child of the GlDropdownItem + const findResponsiveDropdownItems = () => findResponsiveDropdown().findAll('[role="menuitem"]'); + const findResponsiveDropdownItemsAsModel = () => + findResponsiveDropdownItems().wrappers.map((x) => ({ + disabled: x.attributes('disabled'), + href: x.attributes('href'), + title: x.attributes('title'), + text: x.text(), + })); beforeEach(() => { gon.relative_url_root = '/foo/'; @@ -144,42 +166,108 @@ describe('Snippet header component', () => { expect(text).toBe('Authored 1 month ago'); }); - it('renders action buttons based on permissions', () => { - createComponent({ - permissions: { - adminSnippet: false, - updateSnippet: false, + it('renders a action buttons', () => { + createComponent(); + + expect(findButtonsAsModel()).toEqual([ + { + category: 'primary', + disabled: false, + href: `${snippet.webUrl}/edit`, + text: 'Edit', + variant: 'default', }, - }); - expect(buttonCount()).toEqual(0); + { + category: 'secondary', + disabled: false, + text: 'Delete', + variant: 'danger', + }, + { + category: 'primary', + disabled: false, + href: reportAbusePath, + text: 'Submit as spam', + variant: 'default', + }, + ]); + }); - createComponent({ - permissions: { - adminSnippet: true, - updateSnippet: false, + it('renders responsive dropdown for action buttons', () => { + createComponent(); + + expect(findResponsiveDropdownItemsAsModel()).toEqual([ + { + href: `${snippet.webUrl}/edit`, + text: 'Edit', }, - }); - expect(buttonCount()).toEqual(1); + { + text: 'Delete', + }, + { + href: reportAbusePath, + text: 'Submit as spam', + title: 'Submit as spam', + }, + ]); + }); + it.each` + permissions | buttons + ${{ adminSnippet: false, updateSnippet: false }} | ${['Submit as spam']} + ${{ adminSnippet: true, updateSnippet: false }} | ${['Delete', 'Submit as spam']} + ${{ adminSnippet: false, updateSnippet: true }} | ${['Edit', 'Submit as spam']} + `('with permissions ($permissions), renders buttons ($buttons)', ({ permissions, buttons }) => { createComponent({ permissions: { - adminSnippet: true, - updateSnippet: true, + ...permissions, }, }); - expect(buttonCount()).toEqual(2); - createComponent({ - permissions: { - adminSnippet: true, - updateSnippet: true, - }, + expect(findButtonsAsModel().map((x) => x.text)).toEqual(buttons); + }); + + it('with canCreateSnippet permission, renders create button', async () => { + createComponent(); + + // TODO: we should avoid `wrapper.setData` since they + // are component internals. Let's use the apollo mock helpers + // in a follow-up. + wrapper.setData({ canCreateSnippet: true }); + await wrapper.vm.$nextTick(); + + expect(findButtonsAsModel()).toEqual( + expect.arrayContaining([ + { + category: 'secondary', + disabled: false, + href: `/foo/-/snippets/new`, + text: 'New snippet', + variant: 'success', + }, + ]), + ); + }); + + describe('with guest user', () => { + beforeEach(() => { + createComponent({ + permissions: { + adminSnippet: false, + updateSnippet: false, + }, + provide: { + reportAbusePath: null, + }, + }); }); - wrapper.setData({ - canCreateSnippet: true, + + it('does not show any action buttons', () => { + expect(findButtons()).toHaveLength(0); }); - return wrapper.vm.$nextTick().then(() => { - expect(buttonCount()).toEqual(3); + + it('does not show responsive action dropdown', () => { + expect(findResponsiveDropdown().exists()).toBe(false); }); }); @@ -221,6 +309,8 @@ describe('Snippet header component', () => { }); describe('in case of successful mutation, closes modal and redirects to correct listing', () => { + useMockLocationHelper(); + const createDeleteSnippet = (snippetProps = {}) => { createComponent({ snippetProps, diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js index 19e4f2d8c92..786dfabb990 100644 --- a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js +++ b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js @@ -1,4 +1,3 @@ -import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import ToolbarButton from '~/vue_shared/components/markdown/toolbar_button.vue'; @@ -26,7 +25,7 @@ describe('toolbar_button', () => { }); const getButtonShortcutsAttr = () => { - return wrapper.find(GlButton).attributes('data-md-shortcuts'); + return wrapper.find('button').attributes('data-md-shortcuts'); }; describe('keyboard shortcuts', () => { diff --git a/spec/helpers/snippets_helper_spec.rb b/spec/helpers/snippets_helper_spec.rb index 35882c9337b..12d791d8710 100644 --- a/spec/helpers/snippets_helper_spec.rb +++ b/spec/helpers/snippets_helper_spec.rb @@ -92,4 +92,23 @@ RSpec.describe SnippetsHelper do end end end + + describe '#snippet_report_abuse_path' do + let(:snippet) { public_personal_snippet } + let(:current_user) { create(:user) } + + subject { snippet_report_abuse_path(snippet) } + + it 'returns false if the user cannot submit the snippet as spam' do + allow(snippet).to receive(:submittable_as_spam_by?).and_return(false) + + expect(subject).to be_falsey + end + + it 'returns true if the user can submit the snippet as spam' do + allow(snippet).to receive(:submittable_as_spam_by?).and_return(true) + + expect(subject).to be_truthy + end + end end diff --git a/spec/lib/gitlab/ci/reports/security/reports_spec.rb b/spec/lib/gitlab/ci/reports/security/reports_spec.rb index d6a18828120..9b1e02f1418 100644 --- a/spec/lib/gitlab/ci/reports/security/reports_spec.rb +++ b/spec/lib/gitlab/ci/reports/security/reports_spec.rb @@ -54,27 +54,25 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do end describe "#violates_default_policy_against?" do - let(:low_severity_sast) { build(:ci_reports_security_finding, severity: 'low', report_type: :sast) } let(:high_severity_dast) { build(:ci_reports_security_finding, severity: 'high', report_type: :dast) } let(:vulnerabilities_allowed) { 0 } + let(:severity_levels) { %w(critical high) } - subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed) } + subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels) } + + before do + security_reports.get_report('sast', artifact).add_finding(high_severity_dast) + end context 'when the target_reports is `nil`' do let(:target_reports) { nil } - context "when a report has unsafe vulnerability" do - before do - security_reports.get_report('sast', artifact).add_finding(high_severity_dast) - end - + context 'with severity levels matching the existing vulnerabilities' do it { is_expected.to be(true) } end - context "when none of the reports have an unsafe vulnerability" do - before do - security_reports.get_report('sast', artifact).add_finding(low_severity_sast) - end + context "without any severity levels matching the existing vulnerabilities" do + let(:severity_levels) { %w(critical) } it { is_expected.to be(false) } end @@ -84,10 +82,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do let(:target_reports) { described_class.new(pipeline) } context "when a report has a new unsafe vulnerability" do - before do - security_reports.get_report('sast', artifact).add_finding(high_severity_dast) - security_reports.get_report('dependency_scanning', artifact).add_finding(low_severity_sast) - target_reports.get_report('dependency_scanning', artifact).add_finding(low_severity_sast) + context 'with severity levels matching the existing vulnerabilities' do + it { is_expected.to be(true) } end it { is_expected.to be(true) } @@ -97,12 +93,16 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do it { is_expected.to be(false) } end + + context "without any severity levels matching the existing vulnerabilities" do + let(:severity_levels) { %w(critical) } + + it { is_expected.to be(false) } + end end context "when none of the reports have a new unsafe vulnerability" do before do - security_reports.get_report('sast', artifact).add_finding(high_severity_dast) - security_reports.get_report('sast', artifact).add_finding(low_severity_sast) target_reports.get_report('sast', artifact).add_finding(high_severity_dast) end |