diff options
Diffstat (limited to 'spec')
39 files changed, 313 insertions, 350 deletions
diff --git a/spec/factories/clusters/agents/group_authorizations.rb b/spec/factories/clusters/agents/authorizations/ci_access/group_authorizations.rb index abe25794234..659114eef8e 100644 --- a/spec/factories/clusters/agents/group_authorizations.rb +++ b/spec/factories/clusters/agents/authorizations/ci_access/group_authorizations.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true FactoryBot.define do - factory :agent_group_authorization, class: 'Clusters::Agents::GroupAuthorization' do + factory :agent_ci_access_group_authorization, class: 'Clusters::Agents::Authorizations::CiAccess::GroupAuthorization' do association :agent, factory: :cluster_agent group diff --git a/spec/factories/clusters/agents/project_authorizations.rb b/spec/factories/clusters/agents/authorizations/ci_access/project_authorizations.rb index eecbfe95bfc..10d4f8fb946 100644 --- a/spec/factories/clusters/agents/project_authorizations.rb +++ b/spec/factories/clusters/agents/authorizations/ci_access/project_authorizations.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true FactoryBot.define do - factory :agent_project_authorization, class: 'Clusters::Agents::ProjectAuthorization' do + factory :agent_ci_access_project_authorization, class: 'Clusters::Agents::Authorizations::CiAccess::ProjectAuthorization' do association :agent, factory: :cluster_agent project diff --git a/spec/finders/clusters/agent_authorizations_finder_spec.rb b/spec/finders/clusters/agents/authorizations/ci_access/finder_spec.rb index f680792d6c4..c311b19139f 100644 --- a/spec/finders/clusters/agent_authorizations_finder_spec.rb +++ b/spec/finders/clusters/agents/authorizations/ci_access/finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Clusters::AgentAuthorizationsFinder do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::Finder, feature_category: :kubernetes_management do describe '#execute' do let_it_be(:top_level_group) { create(:group) } let_it_be(:subgroup1) { create(:group, parent: top_level_group) } @@ -54,34 +54,34 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do let(:unrelated_agent) { create(:cluster_agent) } before do - create(:agent_project_authorization, agent: unrelated_agent, project: requesting_project) + create(:agent_ci_access_project_authorization, agent: unrelated_agent, project: requesting_project) end it { is_expected.to be_empty } end context 'agent configuration project shares a root namespace, but does not belong to an ancestor of the given project' do - let!(:project_authorization) { create(:agent_project_authorization, agent: non_ancestor_agent, project: requesting_project) } + let!(:project_authorization) { create(:agent_ci_access_project_authorization, agent: non_ancestor_agent, project: requesting_project) } it { is_expected.to match_array([project_authorization]) } end context 'with project authorizations present' do - let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project) } + let!(:authorization) { create(:agent_ci_access_project_authorization, agent: production_agent, project: requesting_project) } it { is_expected.to match_array [authorization] } end context 'with overlapping authorizations' do let!(:agent) { create(:cluster_agent, project: requesting_project) } - let!(:project_authorization) { create(:agent_project_authorization, agent: agent, project: requesting_project) } - let!(:group_authorization) { create(:agent_group_authorization, agent: agent, group: bottom_level_group) } + let!(:project_authorization) { create(:agent_ci_access_project_authorization, agent: agent, project: requesting_project) } + let!(:group_authorization) { create(:agent_ci_access_group_authorization, agent: agent, group: bottom_level_group) } it { is_expected.to match_array [project_authorization] } end it_behaves_like 'access_as' do - let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project, config: config) } + let!(:authorization) { create(:agent_ci_access_project_authorization, agent: production_agent, project: requesting_project, config: config) } end end @@ -92,7 +92,7 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do expect(subject.count).to eq(1) authorization = subject.first - expect(authorization).to be_a(Clusters::Agents::ImplicitAuthorization) + expect(authorization).to be_a(Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization) expect(authorization.agent).to eq(associated_agent) end end @@ -102,15 +102,15 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do let(:unrelated_agent) { create(:cluster_agent) } before do - create(:agent_group_authorization, agent: unrelated_agent, group: top_level_group) + create(:agent_ci_access_group_authorization, agent: unrelated_agent, group: top_level_group) end it { is_expected.to be_empty } end context 'multiple agents are authorized for the same group' do - let!(:staging_auth) { create(:agent_group_authorization, agent: staging_agent, group: bottom_level_group) } - let!(:production_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) } + let!(:staging_auth) { create(:agent_ci_access_group_authorization, agent: staging_agent, group: bottom_level_group) } + let!(:production_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: bottom_level_group) } it 'returns authorizations for all agents' do expect(subject).to contain_exactly(staging_auth, production_auth) @@ -118,8 +118,8 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do end context 'a single agent is authorized to more than one matching group' do - let!(:bottom_level_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) } - let!(:top_level_auth) { create(:agent_group_authorization, agent: production_agent, group: top_level_group) } + let!(:bottom_level_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: bottom_level_group) } + let!(:top_level_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: top_level_group) } it 'picks the authorization for the closest group to the requesting project' do expect(subject).to contain_exactly(bottom_level_auth) @@ -127,13 +127,13 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do end context 'agent configuration project does not belong to an ancestor of the authorized group' do - let!(:group_authorization) { create(:agent_group_authorization, agent: non_ancestor_agent, group: bottom_level_group) } + let!(:group_authorization) { create(:agent_ci_access_group_authorization, agent: non_ancestor_agent, group: bottom_level_group) } it { is_expected.to match_array([group_authorization]) } end it_behaves_like 'access_as' do - let!(:authorization) { create(:agent_group_authorization, agent: production_agent, group: top_level_group, config: config) } + let!(:authorization) { create(:agent_ci_access_group_authorization, agent: production_agent, group: top_level_group, config: config) } end end end diff --git a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap index d86fbf81d20..18b63082e4a 100644 --- a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap +++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap @@ -2,7 +2,7 @@ exports[`Design management design index page renders design index 1`] = ` <div - class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" + class="design-detail js-design-detail fixed-top gl-w-full gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" > <div class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative" @@ -115,7 +115,7 @@ exports[`Design management design index page renders design index 1`] = ` exports[`Design management design index page with error GlAlert is rendered in correct position with correct content 1`] = ` <div - class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" + class="design-detail js-design-detail fixed-top gl-w-full gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" > <div class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative" diff --git a/spec/frontend/ml/experiment_tracking/routes/experiments/show/components/experiment_header_spec.js b/spec/frontend/ml/experiment_tracking/routes/experiments/show/components/experiment_header_spec.js new file mode 100644 index 00000000000..b56755043fb --- /dev/null +++ b/spec/frontend/ml/experiment_tracking/routes/experiments/show/components/experiment_header_spec.js @@ -0,0 +1,55 @@ +import { GlButton } from '@gitlab/ui'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ExperimentHeader from '~/ml/experiment_tracking/routes/experiments/show/components/experiment_header.vue'; +import DeleteButton from '~/ml/experiment_tracking/components/delete_button.vue'; +import setWindowLocation from 'helpers/set_window_location_helper'; +import * as urlHelpers from '~/lib/utils/url_utility'; +import { MOCK_EXPERIMENT } from '../mock_data'; + +const DELETE_INFO = { + deletePath: '/delete', + deleteConfirmationText: 'MODAL_BODY', + actionPrimaryText: 'Delete!', + modalTitle: 'MODAL_TITLE', +}; + +describe('~/ml/experiment_tracking/routes/experiments/show/components/experiment_header.vue', () => { + let wrapper; + + const createWrapper = () => { + wrapper = mountExtended(ExperimentHeader, { + propsData: { title: MOCK_EXPERIMENT.name, deleteInfo: DELETE_INFO }, + }); + }; + + const findDeleteButton = () => wrapper.findComponent(DeleteButton); + const findButton = () => wrapper.findComponent(GlButton); + + beforeEach(createWrapper); + + describe('Delete', () => { + it('shows delete button', () => { + expect(findDeleteButton().exists()).toBe(true); + }); + + it('passes the right props', () => { + expect(findDeleteButton().props()).toMatchObject(DELETE_INFO); + }); + }); + + describe('CSV download', () => { + it('shows download CSV button', () => { + expect(findDeleteButton().exists()).toBe(true); + }); + + it('calls the action to download the CSV', () => { + setWindowLocation('https://blah.com/something/1?name=query&orderBy=name'); + jest.spyOn(urlHelpers, 'visitUrl').mockImplementation(() => {}); + + findButton().vm.$emit('click'); + + expect(urlHelpers.visitUrl).toHaveBeenCalledTimes(1); + expect(urlHelpers.visitUrl).toHaveBeenCalledWith('/something/1.csv?name=query&orderBy=name'); + }); + }); +}); diff --git a/spec/frontend/ml/experiment_tracking/routes/experiments/show/ml_experiments_show_spec.js b/spec/frontend/ml/experiment_tracking/routes/experiments/show/ml_experiments_show_spec.js index da011feee66..38b3d96ed11 100644 --- a/spec/frontend/ml/experiment_tracking/routes/experiments/show/ml_experiments_show_spec.js +++ b/spec/frontend/ml/experiment_tracking/routes/experiments/show/ml_experiments_show_spec.js @@ -1,10 +1,10 @@ import { GlAlert, GlTableLite, GlLink, GlEmptyState } from '@gitlab/ui'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import MlExperimentsShow from '~/ml/experiment_tracking/routes/experiments/show/ml_experiments_show.vue'; +import ExperimentHeader from '~/ml/experiment_tracking/routes/experiments/show/components/experiment_header.vue'; import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; import Pagination from '~/vue_shared/components/incubation/pagination.vue'; import setWindowLocation from 'helpers/set_window_location_helper'; -import DeleteButton from '~/ml/experiment_tracking/components/delete_button.vue'; import * as urlHelpers from '~/lib/utils/url_utility'; import { MOCK_START_CURSOR, MOCK_PAGE_INFO, MOCK_CANDIDATES, MOCK_EXPERIMENT } from './mock_data'; @@ -36,7 +36,7 @@ describe('MlExperimentsShow', () => { const findTableRows = () => findTable().findAll('tbody > tr'); const findNthTableRow = (idx) => findTableRows().at(idx); const findColumnInRow = (row, col) => findNthTableRow(row).findAll('td').at(col); - const findDeleteButton = () => wrapper.findComponent(DeleteButton); + const findExperimentHeader = () => wrapper.findComponent(ExperimentHeader); const hrefInRowAndColumn = (row, col) => findColumnInRow(row, col).findComponent(GlLink).attributes().href; @@ -60,8 +60,12 @@ describe('MlExperimentsShow', () => { expect(findPagination().exists()).toBe(false); }); - it('shows delete button', () => { - expect(findDeleteButton().exists()).toBe(true); + it('shows experiment header', () => { + expect(findExperimentHeader().exists()).toBe(true); + }); + + it('passes the correct title to experiment header', () => { + expect(findExperimentHeader().props('title')).toBe(MOCK_EXPERIMENT.name); }); it('does not show table', () => { diff --git a/spec/frontend/search/sidebar/components/scope_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_navigation_spec.js index 3b2d528e1d7..e8737384f27 100644 --- a/spec/frontend/search/sidebar/components/scope_navigation_spec.js +++ b/spec/frontend/search/sidebar/components/scope_navigation_spec.js @@ -121,4 +121,22 @@ describe('ScopeNavigation', () => { expect(findGlNavItemActive().findComponent(GlIcon).exists()).toBe(true); }); }); + + describe.each` + searchTherm | hasBeenCalled + ${null} | ${0} + ${'test'} | ${1} + `('fetchSidebarCount', ({ searchTherm, hasBeenCalled }) => { + beforeEach(() => { + createComponent({ + urlQuery: { + search: searchTherm, + }, + }); + }); + + it('is only called when search term is set', () => { + expect(actionSpies.fetchSidebarCount).toHaveBeenCalledTimes(hasBeenCalled); + }); + }); }); diff --git a/spec/frontend/super_sidebar/components/context_switcher_spec.js b/spec/frontend/super_sidebar/components/context_switcher_spec.js index 434f7263eb9..11da6ef1243 100644 --- a/spec/frontend/super_sidebar/components/context_switcher_spec.js +++ b/spec/frontend/super_sidebar/components/context_switcher_spec.js @@ -25,7 +25,9 @@ jest.mock('~/super_sidebar/utils', () => ({ })); const focusInputMock = jest.fn(); -const persistentLinks = [{ title: 'Explore', link: '/explore', icon: 'compass' }]; +const persistentLinks = [ + { title: 'Explore', link: '/explore', icon: 'compass', link_classes: 'persistent-link-class' }, +]; const username = 'root'; const projectsPath = 'projectsPath'; const groupsPath = 'groupsPath'; @@ -94,8 +96,13 @@ describe('ContextSwitcher component', () => { it('renders the persistent links', () => { const navItems = findNavItems(); + const firstNavItem = navItems.at(0); + expect(navItems.length).toBe(persistentLinks.length); - expect(navItems.at(0).props('item')).toBe(persistentLinks[0]); + expect(firstNavItem.props('item')).toBe(persistentLinks[0]); + expect(firstNavItem.props('linkClasses')).toEqual({ + [persistentLinks[0].link_classes]: persistentLinks[0].link_classes, + }); }); it('passes the placeholder to the search box', () => { diff --git a/spec/frontend/super_sidebar/components/groups_list_spec.js b/spec/frontend/super_sidebar/components/groups_list_spec.js index 4b61991a5db..4fa3303c12f 100644 --- a/spec/frontend/super_sidebar/components/groups_list_spec.js +++ b/spec/frontend/super_sidebar/components/groups_list_spec.js @@ -19,11 +19,14 @@ describe('GroupsList component', () => { const itRendersViewAllItem = () => { it('renders the "View all..." item', () => { - expect(findViewAllLink().props('item')).toEqual({ + const link = findViewAllLink(); + + expect(link.props('item')).toEqual({ icon: 'group', link: viewAllLink, title: s__('Navigation|View all your groups'), }); + expect(link.props('linkClasses')).toEqual({ 'dashboard-shortcuts-groups': true }); }); }; diff --git a/spec/frontend/super_sidebar/components/merge_request_menu_spec.js b/spec/frontend/super_sidebar/components/merge_request_menu_spec.js index 75998ee6c55..9c8fd0556f1 100644 --- a/spec/frontend/super_sidebar/components/merge_request_menu_spec.js +++ b/spec/frontend/super_sidebar/components/merge_request_menu_spec.js @@ -38,6 +38,7 @@ describe('MergeRequestMenu component', () => { expect(link.attributes('data-track-action')).toBe(extraAttrs['data-track-action']); expect(link.attributes('data-track-label')).toBe(extraAttrs['data-track-label']); expect(link.attributes('data-track-property')).toBe(extraAttrs['data-track-property']); + expect(link.attributes('class')).toContain(extraAttrs.class); }); it('renders item count string in badge', () => { diff --git a/spec/frontend/super_sidebar/components/projects_list_spec.js b/spec/frontend/super_sidebar/components/projects_list_spec.js index 284b88ef27e..93a414e1e8c 100644 --- a/spec/frontend/super_sidebar/components/projects_list_spec.js +++ b/spec/frontend/super_sidebar/components/projects_list_spec.js @@ -19,11 +19,14 @@ describe('ProjectsList component', () => { const itRendersViewAllItem = () => { it('renders the "View all..." item', () => { - expect(findViewAllLink().props('item')).toEqual({ + const link = findViewAllLink(); + + expect(link.props('item')).toEqual({ icon: 'project', link: viewAllLink, title: s__('Navigation|View all your projects'), }); + expect(link.props('linkClasses')).toEqual({ 'dashboard-shortcuts-projects': true }); }); }; diff --git a/spec/frontend/super_sidebar/components/super_sidebar_spec.js b/spec/frontend/super_sidebar/components/super_sidebar_spec.js index 6eae650a2a1..d39fa741574 100644 --- a/spec/frontend/super_sidebar/components/super_sidebar_spec.js +++ b/spec/frontend/super_sidebar/components/super_sidebar_spec.js @@ -67,8 +67,20 @@ describe('SuperSidebar component', () => { }); it("does not call the context switcher's focusInput method initially", () => { + createWrapper(); + expect(focusInputMock).not.toHaveBeenCalled(); }); + + it('renders hidden shortcut links', () => { + createWrapper(); + const [linkAttrs] = sidebarData.shortcut_links; + const link = wrapper.find(`.${linkAttrs.css_class}`); + + expect(link.exists()).toBe(true); + expect(link.attributes('href')).toBe(linkAttrs.href); + expect(link.attributes('class')).toContain('gl-display-none'); + }); }); describe('when opening the context switcher', () => { diff --git a/spec/frontend/super_sidebar/components/user_bar_spec.js b/spec/frontend/super_sidebar/components/user_bar_spec.js index 6da49b45829..2ff731aa102 100644 --- a/spec/frontend/super_sidebar/components/user_bar_spec.js +++ b/spec/frontend/super_sidebar/components/user_bar_spec.js @@ -73,6 +73,7 @@ describe('UserBar component', () => { expect(isuesCounter.attributes('data-track-action')).toBe('click_link'); expect(isuesCounter.attributes('data-track-label')).toBe('issues_link'); expect(isuesCounter.attributes('data-track-property')).toBe('nav_core_menu'); + expect(isuesCounter.attributes('class')).toContain('dashboard-shortcuts-issues'); }); it('renders merge requests counter', () => { @@ -92,6 +93,7 @@ describe('UserBar component', () => { expect(todosCounter.attributes('data-track-action')).toBe('click_link'); expect(todosCounter.attributes('data-track-label')).toBe('todos_link'); expect(todosCounter.attributes('data-track-property')).toBe('nav_core_menu'); + expect(todosCounter.attributes('class')).toContain('shortcuts-todos'); }); it('renders branding logo', () => { diff --git a/spec/frontend/super_sidebar/mock_data.js b/spec/frontend/super_sidebar/mock_data.js index 990a4110d4b..0c9449d98a9 100644 --- a/spec/frontend/super_sidebar/mock_data.js +++ b/spec/frontend/super_sidebar/mock_data.js @@ -53,6 +53,7 @@ export const mergeRequestMenuGroup = [ 'data-track-action': 'click_link', 'data-track-label': 'merge_requests_assigned', 'data-track-property': 'nav_core_menu', + class: 'dashboard-shortcuts-merge_requests', }, }, { @@ -63,6 +64,7 @@ export const mergeRequestMenuGroup = [ 'data-track-action': 'click_link', 'data-track-label': 'merge_requests_to_review', 'data-track-property': 'nav_core_menu', + class: 'dashboard-shortcuts-review_requests', }, }, ], @@ -104,6 +106,13 @@ export const sidebarData = { panel_type: 'your_work', update_pins_url: 'path/to/pins', stop_impersonation_path: '/admin/impersonation', + shortcut_links: [ + { + title: 'Shortcut link', + href: '/shortcut-link', + css_class: 'shortcut-link-class', + }, + ], }; export const userMenuMockStatus = { diff --git a/spec/frontend/whats_new/utils/notification_spec.js b/spec/frontend/whats_new/utils/notification_spec.js index dac02ee07bd..8b5663ee764 100644 --- a/spec/frontend/whats_new/utils/notification_spec.js +++ b/spec/frontend/whats_new/utils/notification_spec.js @@ -1,4 +1,5 @@ -import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import htmlWhatsNewNotification from 'test_fixtures_static/whats_new_notification.html'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { setNotification, getVersionDigest } from '~/whats_new/utils/notification'; @@ -12,7 +13,7 @@ describe('~/whats_new/utils/notification', () => { const getAppEl = () => wrapper.querySelector('.app'); beforeEach(() => { - loadHTMLFixture('static/whats_new_notification.html'); + setHTMLFixture(htmlWhatsNewNotification); wrapper = document.querySelector('.whats-new-notification-fixture-root'); }); diff --git a/spec/helpers/sidebars_helper_spec.rb b/spec/helpers/sidebars_helper_spec.rb index c7d5c0cfc4f..3ebfc2c2bb5 100644 --- a/spec/helpers/sidebars_helper_spec.rb +++ b/spec/helpers/sidebars_helper_spec.rb @@ -139,7 +139,24 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do }, pinned_items: %w[foo bar], panel_type: panel_type, - update_pins_url: pins_url + update_pins_url: pins_url, + shortcut_links: [ + { + title: _('Milestones'), + href: dashboard_milestones_path, + css_class: 'dashboard-shortcuts-milestones' + }, + { + title: _('Snippets'), + href: dashboard_snippets_path, + css_class: 'dashboard-shortcuts-snippets' + }, + { + title: _('Activity'), + href: activity_dashboard_path, + css_class: 'dashboard-shortcuts-activity' + } + ] }) end @@ -155,7 +172,8 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do extraAttrs: { 'data-track-action': 'click_link', 'data-track-label': 'merge_requests_assigned', - 'data-track-property': 'nav_core_menu' + 'data-track-property': 'nav_core_menu', + class: 'dashboard-shortcuts-merge_requests' } }, { @@ -165,7 +183,8 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do extraAttrs: { 'data-track-action': 'click_link', 'data-track-label': 'merge_requests_to_review', - 'data-track-property': 'nav_core_menu' + 'data-track-property': 'nav_core_menu', + class: 'dashboard-shortcuts-review_requests' } } ] diff --git a/spec/lib/api/entities/clusters/agent_authorization_spec.rb b/spec/lib/api/entities/clusters/agents/authorizations/ci_access_spec.rb index 3a1deb43bf8..5f41ae6af4b 100644 --- a/spec/lib/api/entities/clusters/agent_authorization_spec.rb +++ b/spec/lib/api/entities/clusters/agents/authorizations/ci_access_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe API::Entities::Clusters::AgentAuthorization do +RSpec.describe API::Entities::Clusters::Agents::Authorizations::CiAccess, feature_category: :kubernetes_management do subject { described_class.new(authorization).as_json } shared_examples 'generic authorization' do @@ -16,20 +16,20 @@ RSpec.describe API::Entities::Clusters::AgentAuthorization do end context 'project authorization' do - let(:authorization) { create(:agent_project_authorization) } + let(:authorization) { create(:agent_ci_access_project_authorization) } include_examples 'generic authorization' end context 'group authorization' do - let(:authorization) { create(:agent_group_authorization) } + let(:authorization) { create(:agent_ci_access_group_authorization) } include_examples 'generic authorization' end context 'implicit authorization' do let(:agent) { create(:cluster_agent) } - let(:authorization) { Clusters::Agents::ImplicitAuthorization.new(agent: agent) } + let(:authorization) { Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization.new(agent: agent) } include_examples 'generic authorization' end diff --git a/spec/lib/gitlab/slug/environment_spec.rb b/spec/lib/gitlab/slug/environment_spec.rb index e8f0fba27b2..8e23ad118d4 100644 --- a/spec/lib/gitlab/slug/environment_spec.rb +++ b/spec/lib/gitlab/slug/environment_spec.rb @@ -1,38 +1,41 @@ # frozen_string_literal: true require 'fast_spec_helper' +require 'rspec-parameterized' -RSpec.describe Gitlab::Slug::Environment do +RSpec.describe Gitlab::Slug::Environment, feature_category: :environment_management do describe '#generate' do - { - "staging-12345678901234567" => "staging-123456789-q517sa", - "9-staging-123456789012345" => "env-9-staging-123-q517sa", - "staging-1234567890123456" => "staging-1234567890123456", - "staging-1234567890123456-" => "staging-123456789-q517sa", - "production" => "production", - "PRODUCTION" => "production-q517sa", - "review/1-foo" => "review-1-foo-q517sa", - "1-foo" => "env-1-foo-q517sa", - "1/foo" => "env-1-foo-q517sa", - "foo-" => "foo", - "foo--bar" => "foo-bar-q517sa", - "foo**bar" => "foo-bar-q517sa", - "*-foo" => "env-foo-q517sa", - "staging-12345678-" => "staging-12345678", - "staging-12345678-01234567" => "staging-12345678-q517sa", - "" => "env-q517sa", - nil => "env-q517sa" - }.each do |name, matcher| - before do - # ('a' * 64).to_i(16).to_s(36).last(6) gives 'q517sa' - allow(Digest::SHA2).to receive(:hexdigest).with(name).and_return('a' * 64) - end + using RSpec::Parameterized::TableSyntax - it "returns a slug matching #{matcher}, given #{name}" do - slug = described_class.new(name).generate + subject { described_class.new(name).generate } - expect(slug).to match(/\A#{matcher}\z/) - end + before do + # ('a' * 64).to_i(16).to_s(36).last(6) gives 'q517sa' + allow(Digest::SHA2).to receive(:hexdigest).with(name.to_s).and_return('a' * 64) + end + + where(:name, :slug) do + "staging-12345678901234567" | "staging-123456789-q517sa" + "9-staging-123456789012345" | "env-9-staging-123-q517sa" + "staging-1234567890123456" | "staging-1234567890123456" + "staging-1234567890123456-" | "staging-123456789-q517sa" + "production" | "production" + "PRODUCTION" | "production-q517sa" + "review/1-foo" | "review-1-foo-q517sa" + "1-foo" | "env-1-foo-q517sa" + "1/foo" | "env-1-foo-q517sa" + "foo-" | "foo" + "foo--bar" | "foo-bar-q517sa" + "foo**bar" | "foo-bar-q517sa" + "*-foo" | "env-foo-q517sa" + "staging-12345678-" | "staging-12345678" + "staging-12345678-01234567" | "staging-12345678-q517sa" + "" | "env-q517sa" + nil | "env-q517sa" + end + + with_them do + it { is_expected.to eq(slug) } end end end diff --git a/spec/migrations/20230411153310_cleanup_bigint_conversion_for_sent_notifications_spec.rb b/spec/migrations/20230411153310_cleanup_bigint_conversion_for_sent_notifications_spec.rb new file mode 100644 index 00000000000..5780aa365da --- /dev/null +++ b/spec/migrations/20230411153310_cleanup_bigint_conversion_for_sent_notifications_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration!('cleanup_bigint_conversion_for_sent_notifications') + +RSpec.describe CleanupBigintConversionForSentNotifications, feature_category: :database do + let(:sent_notifications) { table(:sent_notifications) } + + it 'correctly migrates up and down' do + reversible_migration do |migration| + migration.before -> { + expect(sent_notifications.column_names).to include('id_convert_to_bigint') + } + + migration.after -> { + sent_notifications.reset_column_information + expect(sent_notifications.column_names).not_to include('id_convert_to_bigint') + } + end + end +end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index ee1410ade91..afb39dec208 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -5468,11 +5468,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category: describe '#cluster_agent_authorizations' do let(:pipeline) { create(:ci_empty_pipeline, :created) } - let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization) } + let(:authorization) { instance_double(Clusters::Agents::Authorizations::CiAccess::GroupAuthorization) } let(:finder) { double(execute: [authorization]) } it 'retrieves authorization records from the finder and caches the result' do - expect(Clusters::AgentAuthorizationsFinder).to receive(:new).once + expect(Clusters::Agents::Authorizations::CiAccess::Finder).to receive(:new).once .with(pipeline.project) .and_return(finder) diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb index de67bdb32aa..df8ad861aff 100644 --- a/spec/models/clusters/agent_spec.rb +++ b/spec/models/clusters/agent_spec.rb @@ -8,10 +8,10 @@ RSpec.describe Clusters::Agent do it { is_expected.to belong_to(:created_by_user).class_name('User').optional } it { is_expected.to belong_to(:project).class_name('::Project') } it { is_expected.to have_many(:agent_tokens).class_name('Clusters::AgentToken').order(Clusters::AgentToken.arel_table[:last_used_at].desc.nulls_last) } - it { is_expected.to have_many(:group_authorizations).class_name('Clusters::Agents::GroupAuthorization') } - it { is_expected.to have_many(:authorized_groups).through(:group_authorizations) } - it { is_expected.to have_many(:project_authorizations).class_name('Clusters::Agents::ProjectAuthorization') } - it { is_expected.to have_many(:authorized_projects).through(:project_authorizations).class_name('::Project') } + it { is_expected.to have_many(:ci_access_group_authorizations).class_name('Clusters::Agents::Authorizations::CiAccess::GroupAuthorization') } + it { is_expected.to have_many(:ci_access_authorized_groups).through(:ci_access_group_authorizations) } + it { is_expected.to have_many(:ci_access_project_authorizations).class_name('Clusters::Agents::Authorizations::CiAccess::ProjectAuthorization') } + it { is_expected.to have_many(:ci_access_authorized_projects).through(:ci_access_project_authorizations).class_name('::Project') } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_length_of(:name).is_at_most(63) } diff --git a/spec/models/clusters/agents/group_authorization_spec.rb b/spec/models/clusters/agents/authorizations/ci_access/group_authorization_spec.rb index baeb8f5464e..2864d6583bd 100644 --- a/spec/models/clusters/agents/group_authorization_spec.rb +++ b/spec/models/clusters/agents/authorizations/ci_access/group_authorization_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -RSpec.describe Clusters::Agents::GroupAuthorization do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::GroupAuthorization, feature_category: :kubernetes_management do it { is_expected.to belong_to(:agent).class_name('Clusters::Agent').required } it { is_expected.to belong_to(:group).class_name('::Group').required } it { expect(described_class).to validate_jsonb_schema(['config']) } describe '#config_project' do - let(:record) { create(:agent_group_authorization) } + let(:record) { create(:agent_ci_access_group_authorization) } it { expect(record.config_project).to eq(record.agent.project) } end diff --git a/spec/models/clusters/agents/implicit_authorization_spec.rb b/spec/models/clusters/agents/authorizations/ci_access/implicit_authorization_spec.rb index 1f4c5b1ac9e..9a4f0c28687 100644 --- a/spec/models/clusters/agents/implicit_authorization_spec.rb +++ b/spec/models/clusters/agents/authorizations/ci_access/implicit_authorization_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Clusters::Agents::ImplicitAuthorization do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization, feature_category: :kubernetes_management do let_it_be(:agent) { create(:cluster_agent) } subject { described_class.new(agent: agent) } diff --git a/spec/models/clusters/agents/project_authorization_spec.rb b/spec/models/clusters/agents/authorizations/ci_access/project_authorization_spec.rb index 9ba259356c7..9e2b25e415e 100644 --- a/spec/models/clusters/agents/project_authorization_spec.rb +++ b/spec/models/clusters/agents/authorizations/ci_access/project_authorization_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -RSpec.describe Clusters::Agents::ProjectAuthorization do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::ProjectAuthorization, feature_category: :kubernetes_management do it { is_expected.to belong_to(:agent).class_name('Clusters::Agent').required } it { is_expected.to belong_to(:project).class_name('Project').required } it { expect(described_class).to validate_jsonb_schema(['config']) } describe '#config_project' do - let(:record) { create(:agent_project_authorization) } + let(:record) { create(:agent_ci_access_project_authorization) } it { expect(record.config_project).to eq(record.agent.project) } end diff --git a/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb b/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb deleted file mode 100644 index a4d1a33b3d5..00000000000 --- a/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Clusters::Agents::AuthorizationConfigScopes do - describe '.with_available_ci_access_fields' do - let(:project) { create(:project) } - - let!(:agent_authorization_0) { create(:agent_project_authorization, project: project) } - let!(:agent_authorization_1) { create(:agent_project_authorization, project: project, config: { access_as: {} }) } - let!(:agent_authorization_2) { create(:agent_project_authorization, project: project, config: { access_as: { agent: {} } }) } - let!(:impersonate_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { impersonate: {} } }) } - let!(:ci_user_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { ci_user: {} } }) } - let!(:ci_job_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { ci_job: {} } }) } - let!(:unexpected_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { unexpected: {} } }) } - - subject { Clusters::Agents::ProjectAuthorization.with_available_ci_access_fields(project) } - - it { is_expected.to contain_exactly(agent_authorization_0, agent_authorization_1, agent_authorization_2) } - end -end diff --git a/spec/models/concerns/clusters/agents/authorizations/ci_access/config_scopes_spec.rb b/spec/models/concerns/clusters/agents/authorizations/ci_access/config_scopes_spec.rb new file mode 100644 index 00000000000..c632c639273 --- /dev/null +++ b/spec/models/concerns/clusters/agents/authorizations/ci_access/config_scopes_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Clusters::Agents::Authorizations::CiAccess::ConfigScopes, feature_category: :kubernetes_management do + describe '.with_available_ci_access_fields' do + let(:project) { create(:project) } + + let!(:agent_authorization_0) { create(:agent_ci_access_project_authorization, project: project) } + let!(:agent_authorization_1) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: {} }) } + let!(:agent_authorization_2) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: { agent: {} } }) } + let!(:impersonate_authorization) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: { impersonate: {} } }) } + let!(:ci_user_authorization) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: { ci_user: {} } }) } + let!(:ci_job_authorization) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: { ci_job: {} } }) } + let!(:unexpected_authorization) { create(:agent_ci_access_project_authorization, project: project, config: { access_as: { unexpected: {} } }) } + + subject { Clusters::Agents::Authorizations::CiAccess::ProjectAuthorization.with_available_ci_access_fields(project) } + + it { is_expected.to contain_exactly(agent_authorization_0, agent_authorization_1, agent_authorization_2) } + end +end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index ed2bf26e129..bcfcfa05ddf 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Note do +RSpec.describe Note, feature_category: :team_planning do include RepoHelpers describe 'associations' do @@ -799,20 +799,22 @@ RSpec.describe Note do describe '#system_note_with_references?' do it 'falsey for user-generated notes' do - note = create(:note, system: false) + note = build_stubbed(:note, system: false) expect(note.system_note_with_references?).to be_falsy end context 'when the note might contain cross references' do SystemNoteMetadata.new.cross_reference_types.each do |type| - let(:note) { create(:note, :system) } - let!(:metadata) { create(:system_note_metadata, note: note, action: type) } + context "with #{type}" do + let(:note) { build_stubbed(:note, :system) } + let!(:metadata) { build_stubbed(:system_note_metadata, note: note, action: type) } - it 'delegates to the cross-reference regex' do - expect(note).to receive(:matches_cross_reference_regex?).and_return(false) + it 'delegates to the cross-reference regex' do + expect(note).to receive(:matches_cross_reference_regex?).and_return(false) - note.system_note_with_references? + note.system_note_with_references? + end end end end diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb index 8b3ec59b785..25871beeb4f 100644 --- a/spec/requests/api/ci/jobs_spec.rb +++ b/spec/requests/api/ci/jobs_spec.rb @@ -198,22 +198,22 @@ RSpec.describe API::Ci::Jobs, feature_category: :continuous_integration do let_it_be(:agent_authorizations_without_env) do [ - create(:agent_group_authorization, agent: create(:cluster_agent, project: other_project), group: group), - create(:agent_project_authorization, agent: create(:cluster_agent, project: project), project: project), - Clusters::Agents::ImplicitAuthorization.new(agent: create(:cluster_agent, project: project)) + create(:agent_ci_access_group_authorization, agent: create(:cluster_agent, project: other_project), group: group), + create(:agent_ci_access_project_authorization, agent: create(:cluster_agent, project: project), project: project), + Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization.new(agent: create(:cluster_agent, project: project)) ] end let_it_be(:agent_authorizations_with_review_and_production_env) do [ create( - :agent_group_authorization, + :agent_ci_access_group_authorization, agent: create(:cluster_agent, project: other_project), group: group, environments: ['production', 'review/*'] ), create( - :agent_project_authorization, + :agent_ci_access_project_authorization, agent: create(:cluster_agent, project: project), project: project, environments: ['production', 'review/*'] @@ -224,13 +224,13 @@ RSpec.describe API::Ci::Jobs, feature_category: :continuous_integration do let_it_be(:agent_authorizations_with_staging_env) do [ create( - :agent_group_authorization, + :agent_ci_access_group_authorization, agent: create(:cluster_agent, project: other_project), group: group, environments: ['staging'] ), create( - :agent_project_authorization, + :agent_ci_access_project_authorization, agent: create(:cluster_agent, project: project), project: project, environments: ['staging'] diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb index 547b9071f94..56d6f538026 100644 --- a/spec/requests/api/internal/kubernetes_spec.rb +++ b/spec/requests/api/internal/kubernetes_spec.rb @@ -158,8 +158,8 @@ RSpec.describe API::Internal::Kubernetes, feature_category: :kubernetes_manageme send_request(params: { agent_id: agent.id, agent_config: config }) expect(response).to have_gitlab_http_status(:no_content) - expect(agent.authorized_groups).to contain_exactly(group) - expect(agent.authorized_projects).to contain_exactly(project) + expect(agent.ci_access_authorized_groups).to contain_exactly(group) + expect(agent.ci_access_authorized_projects).to contain_exactly(project) end end diff --git a/spec/scripts/review_apps/automated_cleanup_spec.rb b/spec/scripts/review_apps/automated_cleanup_spec.rb index 40cf0a8bf75..a8b8353d2ef 100644 --- a/spec/scripts/review_apps/automated_cleanup_spec.rb +++ b/spec/scripts/review_apps/automated_cleanup_spec.rb @@ -30,7 +30,6 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do allow(Tooling::Helm3Client).to receive(:new).and_return(helm_client) allow(Tooling::KubernetesClient).to receive(:new).and_return(kubernetes_client) - allow(kubernetes_client).to receive(:cleanup_pvcs_by_created_at) allow(kubernetes_client).to receive(:cleanup_namespaces_by_created_at) end @@ -124,28 +123,6 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do end end - describe '#perform_stale_pvc_cleanup!' do - subject { instance.perform_stale_pvc_cleanup!(days: days) } - - let(:days) { 2 } - - it_behaves_like 'the days argument is an integer in the correct range' - - it 'performs Kubernetes cleanup by created at' do - expect(kubernetes_client).to receive(:cleanup_pvcs_by_created_at).with(created_before: two_days_ago) - - subject - end - - context 'when the dry-run flag is true' do - let(:dry_run) { true } - - it 'does not delete anything' do - expect(kubernetes_client).not_to receive(:cleanup_pvcs_by_created_at) - end - end - end - describe '#perform_stale_namespace_cleanup!' do subject { instance.perform_stale_namespace_cleanup!(days: days) } diff --git a/spec/services/ci/generate_kubeconfig_service_spec.rb b/spec/services/ci/generate_kubeconfig_service_spec.rb index da18dfe04c3..913aaf11d7d 100644 --- a/spec/services/ci/generate_kubeconfig_service_spec.rb +++ b/spec/services/ci/generate_kubeconfig_service_spec.rb @@ -13,12 +13,12 @@ RSpec.describe Ci::GenerateKubeconfigService, feature_category: :kubernetes_mana let_it_be(:project_agent_authorization) do agent = create(:cluster_agent, project: agent_project) - create(:agent_project_authorization, agent: agent, project: project) + create(:agent_ci_access_project_authorization, agent: agent, project: project) end let_it_be(:group_agent_authorization) do agent = create(:cluster_agent, project: agent_project) - create(:agent_group_authorization, agent: agent, group: group) + create(:agent_ci_access_group_authorization, agent: agent, group: group) end let(:template) do @@ -33,7 +33,7 @@ RSpec.describe Ci::GenerateKubeconfigService, feature_category: :kubernetes_mana let(:agent_authorizations) { [project_agent_authorization, group_agent_authorization] } let(:filter_service) do instance_double( - ::Clusters::Agents::FilterAuthorizationsService, + ::Clusters::Agents::Authorizations::CiAccess::FilterService, execute: agent_authorizations ) end @@ -42,7 +42,7 @@ RSpec.describe Ci::GenerateKubeconfigService, feature_category: :kubernetes_mana before do allow(Gitlab::Kubernetes::Kubeconfig::Template).to receive(:new).and_return(template) - allow(::Clusters::Agents::FilterAuthorizationsService).to receive(:new).and_return(filter_service) + allow(::Clusters::Agents::Authorizations::CiAccess::FilterService).to receive(:new).and_return(filter_service) end it 'returns a Kubeconfig Template' do @@ -59,7 +59,7 @@ RSpec.describe Ci::GenerateKubeconfigService, feature_category: :kubernetes_mana end it "filters the pipeline's agents by `nil` environment" do - expect(::Clusters::Agents::FilterAuthorizationsService).to receive(:new).with( + expect(::Clusters::Agents::Authorizations::CiAccess::FilterService).to receive(:new).with( pipeline.cluster_agent_authorizations, environment: nil ) @@ -89,7 +89,7 @@ RSpec.describe Ci::GenerateKubeconfigService, feature_category: :kubernetes_mana subject(:execute) { described_class.new(pipeline, token: build.token, environment: 'production').execute } it "filters the pipeline's agents by the specified environment" do - expect(::Clusters::Agents::FilterAuthorizationsService).to receive(:new).with( + expect(::Clusters::Agents::Authorizations::CiAccess::FilterService).to receive(:new).with( pipeline.cluster_agent_authorizations, environment: 'production' ) diff --git a/spec/services/clusters/agents/filter_authorizations_service_spec.rb b/spec/services/clusters/agents/authorizations/ci_access/filter_service_spec.rb index 62cff405d0c..45443cfd887 100644 --- a/spec/services/clusters/agents/filter_authorizations_service_spec.rb +++ b/spec/services/clusters/agents/authorizations/ci_access/filter_service_spec.rb @@ -2,16 +2,16 @@ require 'spec_helper' -RSpec.describe Clusters::Agents::FilterAuthorizationsService, feature_category: :continuous_integration do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::FilterService, feature_category: :continuous_integration do describe '#execute' do let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group) } let(:agent_authorizations_without_env) do [ - build(:agent_project_authorization, project: project, agent: build(:cluster_agent, project: project)), - build(:agent_group_authorization, group: group, agent: build(:cluster_agent, project: project)), - ::Clusters::Agents::ImplicitAuthorization.new(agent: build(:cluster_agent, project: project)) + build(:agent_ci_access_project_authorization, project: project, agent: build(:cluster_agent, project: project)), + build(:agent_ci_access_group_authorization, group: group, agent: build(:cluster_agent, project: project)), + ::Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization.new(agent: build(:cluster_agent, project: project)) ] end @@ -31,13 +31,13 @@ RSpec.describe Clusters::Agents::FilterAuthorizationsService, feature_category: let(:agent_authorizations_with_env) do [ build( - :agent_project_authorization, + :agent_ci_access_project_authorization, project: project, agent: build(:cluster_agent, project: project), environments: ['staging', 'review/*', 'production'] ), build( - :agent_group_authorization, + :agent_ci_access_group_authorization, group: group, agent: build(:cluster_agent, project: project), environments: ['staging', 'review/*', 'production'] @@ -48,13 +48,13 @@ RSpec.describe Clusters::Agents::FilterAuthorizationsService, feature_category: let(:agent_authorizations_with_different_env) do [ build( - :agent_project_authorization, + :agent_ci_access_project_authorization, project: project, agent: build(:cluster_agent, project: project), environments: ['staging'] ), build( - :agent_group_authorization, + :agent_ci_access_group_authorization, group: group, agent: build(:cluster_agent, project: project), environments: ['staging'] diff --git a/spec/services/clusters/agents/refresh_authorization_service_spec.rb b/spec/services/clusters/agents/authorizations/ci_access/refresh_service_spec.rb index 51c054ddc98..dc803c94ccb 100644 --- a/spec/services/clusters/agents/refresh_authorization_service_spec.rb +++ b/spec/services/clusters/agents/authorizations/ci_access/refresh_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: :kubernetes_management do +RSpec.describe Clusters::Agents::Authorizations::CiAccess::RefreshService, feature_category: :kubernetes_management do describe '#execute' do let_it_be(:root_ancestor) { create(:group) } @@ -39,11 +39,11 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: before do default_config = { default_namespace: 'default' } - agent.group_authorizations.create!(group: removed_group, config: default_config) - agent.group_authorizations.create!(group: modified_group, config: default_config) + agent.ci_access_group_authorizations.create!(group: removed_group, config: default_config) + agent.ci_access_group_authorizations.create!(group: modified_group, config: default_config) - agent.project_authorizations.create!(project: removed_project, config: default_config) - agent.project_authorizations.create!(project: modified_project, config: default_config) + agent.ci_access_project_authorizations.create!(project: removed_project, config: default_config) + agent.ci_access_project_authorizations.create!(project: modified_project, config: default_config) end shared_examples 'removing authorization' do @@ -78,12 +78,12 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: describe 'group authorization' do it 'refreshes authorizations for the agent' do expect(subject).to be_truthy - expect(agent.authorized_groups).to contain_exactly(added_group, modified_group) + expect(agent.ci_access_authorized_groups).to contain_exactly(added_group, modified_group) - added_authorization = agent.group_authorizations.find_by(group: added_group) + added_authorization = agent.ci_access_group_authorizations.find_by(group: added_group) expect(added_authorization.config).to eq({ 'default_namespace' => 'default' }) - modified_authorization = agent.group_authorizations.find_by(group: modified_group) + modified_authorization = agent.ci_access_group_authorizations.find_by(group: modified_group) expect(modified_authorization.config).to eq({ 'default_namespace' => 'new-namespace' }) end @@ -94,24 +94,24 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: it 'authorizes groups up to the limit' do expect(subject).to be_truthy - expect(agent.authorized_groups).to contain_exactly(added_group) + expect(agent.ci_access_authorized_groups).to contain_exactly(added_group) end end include_examples 'removing authorization' do - let(:authorizations) { agent.authorized_groups } + let(:authorizations) { agent.ci_access_authorized_groups } end end describe 'project authorization' do it 'refreshes authorizations for the agent' do expect(subject).to be_truthy - expect(agent.authorized_projects).to contain_exactly(added_project, modified_project) + expect(agent.ci_access_authorized_projects).to contain_exactly(added_project, modified_project) - added_authorization = agent.project_authorizations.find_by(project: added_project) + added_authorization = agent.ci_access_project_authorizations.find_by(project: added_project) expect(added_authorization.config).to eq({ 'default_namespace' => 'default' }) - modified_authorization = agent.project_authorizations.find_by(project: modified_project) + modified_authorization = agent.ci_access_project_authorizations.find_by(project: modified_project) expect(modified_authorization.config).to eq({ 'default_namespace' => 'new-namespace' }) end @@ -121,7 +121,7 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: it 'creates an authorization record for the project' do expect(subject).to be_truthy - expect(agent.authorized_projects).to contain_exactly(added_project) + expect(agent.ci_access_authorized_projects).to contain_exactly(added_project) end end @@ -131,7 +131,7 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: it 'creates an authorization record for the project' do expect(subject).to be_truthy - expect(agent.authorized_projects).to contain_exactly(added_project) + expect(agent.ci_access_authorized_projects).to contain_exactly(added_project) end end @@ -142,12 +142,12 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService, feature_category: it 'authorizes projects up to the limit' do expect(subject).to be_truthy - expect(agent.authorized_projects).to contain_exactly(added_project) + expect(agent.ci_access_authorized_projects).to contain_exactly(added_project) end end include_examples 'removing authorization' do - let(:authorizations) { agent.authorized_projects } + let(:authorizations) { agent.ci_access_authorized_projects } end end end diff --git a/spec/services/security/ci_configuration/dependency_scanning_create_service_spec.rb b/spec/services/security/ci_configuration/dependency_scanning_create_service_spec.rb index 719a2cf24e9..7ac2249642a 100644 --- a/spec/services/security/ci_configuration/dependency_scanning_create_service_spec.rb +++ b/spec/services/security/ci_configuration/dependency_scanning_create_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Security::CiConfiguration::DependencyScanningCreateService, :snowplow, - feature_category: :dependency_scanning do + feature_category: :software_composition_analysis do subject(:result) { described_class.new(project, user).execute } let(:branch_name) { 'set-dependency-scanning-config-1' } diff --git a/spec/support/finder_collection_allowlist.yml b/spec/support/finder_collection_allowlist.yml index 1b1c98af80d..25084ece58d 100644 --- a/spec/support/finder_collection_allowlist.yml +++ b/spec/support/finder_collection_allowlist.yml @@ -24,7 +24,7 @@ - Ci::CommitStatusesFinder - Ci::DailyBuildGroupReportResultsFinder - ClusterAncestorsFinder -- Clusters::AgentAuthorizationsFinder +- Clusters::Agents::Authorizations::CiAccess::Finder - Clusters::KubernetesNamespaceFinder - ComplianceManagement::MergeRequests::ComplianceViolationsFinder - ContainerRepositoriesFinder diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index a767ae69653..1c26a34010c 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -7205,7 +7205,6 @@ - './spec/lib/gitlab/slash_commands/presenters/issue_show_spec.rb' - './spec/lib/gitlab/slash_commands/presenters/run_spec.rb' - './spec/lib/gitlab/slash_commands/run_spec.rb' -- './spec/lib/gitlab/slug/environment_spec.rb' - './spec/lib/gitlab/snippet_search_results_spec.rb' - './spec/lib/gitlab/sourcegraph_spec.rb' - './spec/lib/gitlab/spamcheck/client_spec.rb' diff --git a/spec/tooling/lib/tooling/kubernetes_client_spec.rb b/spec/tooling/lib/tooling/kubernetes_client_spec.rb index 20eb78c2f4f..8d127f1345b 100644 --- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb +++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb @@ -14,88 +14,6 @@ RSpec.describe Tooling::KubernetesClient do allow(instance).to receive(:run_command) end - describe '#cleanup_pvcs_by_created_at' do - let(:pvc_1_created_at) { three_days_ago } - let(:pvc_2_created_at) { three_days_ago } - let(:pvc_1_namespace) { 'review-first-review-app' } - let(:pvc_2_namespace) { 'review-second-review-app' } - let(:kubectl_pvcs_json) do - <<~JSON - { - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "PersistentVolumeClaim", - "metadata": { - "creationTimestamp": "#{pvc_1_created_at.utc.iso8601}", - "name": "pvc1", - "namespace": "#{pvc_1_namespace}" - } - }, - { - "apiVersion": "v1", - "kind": "PersistentVolumeClaim", - "metadata": { - "creationTimestamp": "#{pvc_2_created_at.utc.iso8601}", - "name": "pvc2", - "namespace": "#{pvc_2_namespace}" - } - } - ] - } - JSON - end - - subject { instance.cleanup_pvcs_by_created_at(created_before: two_days_ago) } - - before do - allow(instance).to receive(:run_command).with( - "kubectl get pvc --all-namespaces --sort-by='{.metadata.creationTimestamp}' -o json" - ).and_return(kubectl_pvcs_json) - end - - context 'when no pvcs are stale' do - let(:pvc_1_created_at) { one_day_ago } - let(:pvc_2_created_at) { one_day_ago } - - it 'does not delete any PVC' do - expect(instance).not_to receive(:run_command).with(/kubectl delete pvc/) - - subject - end - end - - context 'when some pvcs are stale' do - let(:pvc_1_created_at) { three_days_ago } - let(:pvc_2_created_at) { three_days_ago } - - context 'when some pvcs are not in a review app namespaces' do - let(:pvc_1_namespace) { 'review-my-review-app' } - let(:pvc_2_namespace) { 'review-apps' } # This is not a review apps namespace, so we should not delete PVCs inside it - - it 'deletes the stale pvcs inside of review-apps namespaces only' do - expect(instance).to receive(:run_command).with("kubectl delete pvc --namespace=#{pvc_1_namespace} --now --ignore-not-found pvc1") - expect(instance).not_to receive(:run_command).with(/kubectl delete pvc --namespace=#{pvc_2_namespace}/) - - subject - end - end - - context 'when all pvcs are in review-apps namespaces' do - let(:pvc_1_namespace) { 'review-my-review-app' } - let(:pvc_2_namespace) { 'review-another-review-app' } - - it 'deletes all of the stale pvcs' do - expect(instance).to receive(:run_command).with("kubectl delete pvc --namespace=#{pvc_1_namespace} --now --ignore-not-found pvc1") - expect(instance).to receive(:run_command).with("kubectl delete pvc --namespace=#{pvc_2_namespace} --now --ignore-not-found pvc2") - - subject - end - end - end - end - describe '#cleanup_namespaces_by_created_at' do let(:namespace_1_created_at) { three_days_ago } let(:namespace_2_created_at) { three_days_ago } @@ -174,32 +92,6 @@ RSpec.describe Tooling::KubernetesClient do end end - describe '#delete_pvc' do - let(:pvc_name) { 'my-pvc' } - - subject { instance.delete_pvc(pvc_name, pvc_namespace) } - - context 'when the namespace is not a review app namespace' do - let(:pvc_namespace) { 'not-a-review-app-namespace' } - - it 'does not delete the pvc' do - expect(instance).not_to receive(:run_command).with(/kubectl delete pvc/) - - subject - end - end - - context 'when the namespace is a review app namespace' do - let(:pvc_namespace) { 'review-apple-test' } - - it 'deletes the pvc' do - expect(instance).to receive(:run_command).with("kubectl delete pvc --namespace=#{pvc_namespace} --now --ignore-not-found #{pvc_name}") - - subject - end - end - end - describe '#delete_namespaces' do subject { instance.delete_namespaces(namespaces) } @@ -224,70 +116,11 @@ RSpec.describe Tooling::KubernetesClient do end end - describe '#pvcs_created_before' do - subject { instance.pvcs_created_before(created_before: two_days_ago) } - - let(:pvc_1_created_at) { three_days_ago } - let(:pvc_2_created_at) { three_days_ago } - let(:pvc_1_namespace) { 'review-first-review-app' } - let(:pvc_2_namespace) { 'review-second-review-app' } - let(:kubectl_pvcs_json) do - <<~JSON - { - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "PersistentVolumeClaim", - "metadata": { - "creationTimestamp": "#{pvc_1_created_at.utc.iso8601}", - "name": "pvc1", - "namespace": "#{pvc_1_namespace}" - } - }, - { - "apiVersion": "v1", - "kind": "PersistentVolumeClaim", - "metadata": { - "creationTimestamp": "#{pvc_2_created_at.utc.iso8601}", - "name": "pvc2", - "namespace": "#{pvc_2_namespace}" - } - } - ] - } - JSON - end - - it 'calls #resource_created_before with the correct parameters' do - expect(instance).to receive(:resource_created_before).with(resource_type: 'pvc', created_before: two_days_ago) - - subject - end - - it 'returns a hash with two keys' do - allow(instance).to receive(:run_command).with( - "kubectl get pvc --all-namespaces --sort-by='{.metadata.creationTimestamp}' -o json" - ).and_return(kubectl_pvcs_json) - - expect(subject).to match_array([ - { - resource_name: 'pvc1', - namespace: 'review-first-review-app' - }, - { - resource_name: 'pvc2', - namespace: 'review-second-review-app' - } - ]) - end - end - describe '#namespaces_created_before' do subject { instance.namespaces_created_before(created_before: two_days_ago) } let(:namespace_1_created_at) { three_days_ago } - let(:namespace_2_created_at) { three_days_ago } + let(:namespace_2_created_at) { one_day_ago } let(:namespace_1_name) { 'review-first-review-app' } let(:namespace_2_name) { 'review-second-review-app' } let(:kubectl_namespaces_json) do @@ -316,18 +149,12 @@ RSpec.describe Tooling::KubernetesClient do JSON end - it 'calls #resource_created_before with the correct parameters' do - expect(instance).to receive(:resource_created_before).with(resource_type: 'namespace', created_before: two_days_ago) - - subject - end - it 'returns an array of namespaces' do allow(instance).to receive(:run_command).with( "kubectl get namespace --all-namespaces --sort-by='{.metadata.creationTimestamp}' -o json" ).and_return(kubectl_namespaces_json) - expect(subject).to match_array(%w[review-first-review-app review-second-review-app]) + expect(subject).to match_array(%w[review-first-review-app]) end end diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb index ed71a03c7e0..832cc5b7cf3 100644 --- a/spec/views/search/_results.html.haml_spec.rb +++ b/spec/views/search/_results.html.haml_spec.rb @@ -97,12 +97,6 @@ RSpec.describe 'search/_results', feature_category: :global_search do expect(rendered).not_to have_selector('[data-track-property=search_result]') end end - - it 'does render the sidebar' do - render - - expect(rendered).to have_selector('#js-search-sidebar') - end end end diff --git a/spec/views/search/show.html.haml_spec.rb b/spec/views/search/show.html.haml_spec.rb index db06adfeb6b..0158a9049b9 100644 --- a/spec/views/search/show.html.haml_spec.rb +++ b/spec/views/search/show.html.haml_spec.rb @@ -41,6 +41,12 @@ RSpec.describe 'search/show', feature_category: :global_search do expect(rendered).not_to render_template('search/_results') end + + it 'does render the sidebar' do + render + + expect(rendered).to have_selector('#js-search-sidebar') + end end context 'unfurling support' do |