diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-09 00:11:09 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-09 00:11:09 +0300 |
commit | 3d42e098d9658853984534c9dfc2bf76284a8ac0 (patch) | |
tree | 269e9d9e017124f5f6d841311661832ea7e4eff8 /spec | |
parent | a3487798aeff89daff78749e6d6f392d3ca23687 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/explore/groups_controller_spec.rb | 8 | ||||
-rw-r--r-- | spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js | 15 | ||||
-rw-r--r-- | spec/frontend/gitlab_version_check/components/security_patch_upgrade_alert_spec.js | 84 | ||||
-rw-r--r-- | spec/frontend/gitlab_version_check/index_spec.js | 19 | ||||
-rw-r--r-- | spec/frontend/gitlab_version_check/mock_data.js | 6 | ||||
-rw-r--r-- | spec/frontend/token_access/inbound_token_access_spec.js | 311 | ||||
-rw-r--r-- | spec/frontend/token_access/mock_data.js | 96 | ||||
-rw-r--r-- | spec/frontend/token_access/outbound_token_access_spec.js (renamed from spec/frontend/token_access/token_access_spec.js) | 25 | ||||
-rw-r--r-- | spec/frontend/token_access/token_access_app_spec.js | 47 | ||||
-rw-r--r-- | spec/frontend/token_access/token_projects_table_spec.js | 7 | ||||
-rw-r--r-- | spec/helpers/version_check_helper_spec.rb | 31 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 51 | ||||
-rw-r--r-- | spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb | 4 |
13 files changed, 501 insertions, 203 deletions
diff --git a/spec/controllers/explore/groups_controller_spec.rb b/spec/controllers/explore/groups_controller_spec.rb index d53cb233df9..a3bd8102462 100644 --- a/spec/controllers/explore/groups_controller_spec.rb +++ b/spec/controllers/explore/groups_controller_spec.rb @@ -40,4 +40,12 @@ RSpec.describe Explore::GroupsController do end it_behaves_like 'explore groups' + + context 'generic_explore_groups flag is disabled' do + before do + stub_feature_flags(generic_explore_groups: false) + end + + it_behaves_like 'explore groups' + end end diff --git a/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js b/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js index a23f8370adf..d4fc47601cf 100644 --- a/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js +++ b/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js @@ -1,10 +1,9 @@ -import { GlDropdown } from '@gitlab/ui'; +import { GlDisclosureDropdown } from '@gitlab/ui'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import ToolbarMoreDropdown from '~/content_editor/components/toolbar_more_dropdown.vue'; import Diagram from '~/content_editor/extensions/diagram'; import HorizontalRule from '~/content_editor/extensions/horizontal_rule'; import eventHubFactory from '~/helpers/event_hub_factory'; -import { stubComponent } from 'helpers/stub_component'; import { createTestEditor, mockChainedCommands, emitEditorEvent } from '../test_utils'; describe('content_editor/components/toolbar_more_dropdown', () => { @@ -25,14 +24,11 @@ describe('content_editor/components/toolbar_more_dropdown', () => { tiptapEditor, eventHub, }, - stubs: { - GlDropdown: stubComponent(GlDropdown), - }, propsData, }); }; - const findDropdown = () => wrapper.findComponent(GlDropdown); + const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown); beforeEach(() => { buildEditor(); @@ -60,7 +56,7 @@ describe('content_editor/components/toolbar_more_dropdown', () => { beforeEach(async () => { commands = mockChainedCommands(tiptapEditor, [command, 'focus', 'run']); - btn = wrapper.findByRole('menuitem', { name }); + btn = wrapper.findByRole('button', { name }); }); it(`inserts a ${contentType}`, async () => { @@ -76,12 +72,11 @@ describe('content_editor/components/toolbar_more_dropdown', () => { }); describe('a11y tests', () => { - it('sets text, title, and text-sr-only properties to the table button dropdown', () => { + it('sets toggleText and text-sr-only properties to the table button dropdown', () => { expect(findDropdown().props()).toMatchObject({ - text: 'More', textSrOnly: true, + toggleText: 'More options', }); - expect(findDropdown().attributes('title')).toBe('More'); }); }); }); diff --git a/spec/frontend/gitlab_version_check/components/security_patch_upgrade_alert_spec.js b/spec/frontend/gitlab_version_check/components/security_patch_upgrade_alert_spec.js deleted file mode 100644 index 665dacd5c47..00000000000 --- a/spec/frontend/gitlab_version_check/components/security_patch_upgrade_alert_spec.js +++ /dev/null @@ -1,84 +0,0 @@ -import { GlAlert, GlButton, GlLink, GlSprintf } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; -import SecurityPatchUpgradeAlert from '~/gitlab_version_check/components/security_patch_upgrade_alert.vue'; -import { UPGRADE_DOCS_URL, ABOUT_RELEASES_PAGE } from '~/gitlab_version_check/constants'; - -describe('SecurityPatchUpgradeAlert', () => { - let wrapper; - let trackingSpy; - - const defaultProps = { - currentVersion: '99.9', - }; - - const createComponent = () => { - trackingSpy = mockTracking(undefined, undefined, jest.spyOn); - - wrapper = shallowMount(SecurityPatchUpgradeAlert, { - propsData: { - ...defaultProps, - }, - stubs: { - GlAlert, - GlSprintf, - }, - }); - }; - - afterEach(() => { - unmockTracking(); - }); - - const findGlAlert = () => wrapper.findComponent(GlAlert); - const findGlButton = () => wrapper.findComponent(GlButton); - const findGlLink = () => wrapper.findComponent(GlLink); - - describe('template', () => { - beforeEach(() => { - createComponent(); - }); - - it('renders non-dismissible GlAlert with version information', () => { - expect(findGlAlert().text()).toContain( - `You are currently on version ${defaultProps.currentVersion}.`, - ); - expect(findGlAlert().props('dismissible')).toBe(false); - }); - - it('tracks render security_patch_upgrade_alert correctly', () => { - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'render', { - label: 'security_patch_upgrade_alert', - property: defaultProps.currentVersion, - }); - }); - - it('renders GlLink with correct text and link', () => { - expect(findGlLink().text()).toBe('Learn more about this critical security release.'); - expect(findGlLink().attributes('href')).toBe(ABOUT_RELEASES_PAGE); - }); - - it('tracks click security_patch_upgrade_alert_learn_more when link is clicked', async () => { - await findGlLink().vm.$emit('click'); - - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_link', { - label: 'security_patch_upgrade_alert_learn_more', - property: defaultProps.currentVersion, - }); - }); - - it('renders GlButton with correct text and link', () => { - expect(findGlButton().text()).toBe('Upgrade now'); - expect(findGlButton().attributes('href')).toBe(UPGRADE_DOCS_URL); - }); - - it('tracks click security_patch_upgrade_alert_upgrade_now when button is clicked', async () => { - await findGlButton().vm.$emit('click'); - - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_link', { - label: 'security_patch_upgrade_alert_upgrade_now', - property: defaultProps.currentVersion, - }); - }); - }); -}); diff --git a/spec/frontend/gitlab_version_check/index_spec.js b/spec/frontend/gitlab_version_check/index_spec.js index 92bc103cede..893105969ed 100644 --- a/spec/frontend/gitlab_version_check/index_spec.js +++ b/spec/frontend/gitlab_version_check/index_spec.js @@ -7,9 +7,6 @@ import { VERSION_CHECK_BADGE_FIXTURE, VERSION_CHECK_BADGE_FINDER, VERSION_BADGE_TEXT, - SECURITY_PATCH_FIXTURE, - SECURITY_PATCH_FINDER, - SECURITY_PATCH_TEXT, SECURITY_MODAL_FIXTURE, SECURITY_MODAL_FINDER, SECURITY_MODAL_TEXT, @@ -29,15 +26,13 @@ describe('initGitlabVersionCheck', () => { }); describe.each` - description | fixture | finders | componentTexts - ${'with no version check elements'} | ${'<div></div>'} | ${[]} | ${[]} - ${'with version check badge el but no prop data'} | ${VERSION_CHECK_BADGE_NO_PROP_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[undefined]} - ${'with version check badge el but no severity data'} | ${VERSION_CHECK_BADGE_NO_SEVERITY_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[undefined]} - ${'with version check badge el and version data'} | ${VERSION_CHECK_BADGE_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[VERSION_BADGE_TEXT]} - ${'with security patch el'} | ${SECURITY_PATCH_FIXTURE} | ${[SECURITY_PATCH_FINDER]} | ${[SECURITY_PATCH_TEXT]} - ${'with security patch and version badge els'} | ${`${SECURITY_PATCH_FIXTURE}${VERSION_CHECK_BADGE_FIXTURE}`} | ${[SECURITY_PATCH_FINDER, VERSION_CHECK_BADGE_FINDER]} | ${[SECURITY_PATCH_TEXT, VERSION_BADGE_TEXT]} - ${'with security modal el'} | ${SECURITY_MODAL_FIXTURE} | ${[SECURITY_MODAL_FINDER]} | ${[SECURITY_MODAL_TEXT]} - ${'with security modal, security patch, and version badge els'} | ${`${SECURITY_PATCH_FIXTURE}${SECURITY_MODAL_FIXTURE}${VERSION_CHECK_BADGE_FIXTURE}`} | ${[SECURITY_PATCH_FINDER, SECURITY_MODAL_FINDER, VERSION_CHECK_BADGE_FINDER]} | ${[SECURITY_PATCH_TEXT, SECURITY_MODAL_TEXT, VERSION_BADGE_TEXT]} + description | fixture | finders | componentTexts + ${'with no version check elements'} | ${'<div></div>'} | ${[]} | ${[]} + ${'with version check badge el but no prop data'} | ${VERSION_CHECK_BADGE_NO_PROP_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[undefined]} + ${'with version check badge el but no severity data'} | ${VERSION_CHECK_BADGE_NO_SEVERITY_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[undefined]} + ${'with version check badge el and version data'} | ${VERSION_CHECK_BADGE_FIXTURE} | ${[VERSION_CHECK_BADGE_FINDER]} | ${[VERSION_BADGE_TEXT]} + ${'with security modal el'} | ${SECURITY_MODAL_FIXTURE} | ${[SECURITY_MODAL_FINDER]} | ${[SECURITY_MODAL_TEXT]} + ${'with security modal and version badge els'} | ${`${SECURITY_MODAL_FIXTURE}${VERSION_CHECK_BADGE_FIXTURE}`} | ${[SECURITY_MODAL_FINDER, VERSION_CHECK_BADGE_FINDER]} | ${[SECURITY_MODAL_TEXT, VERSION_BADGE_TEXT]} `('$description', ({ fixture, finders, componentTexts }) => { beforeEach(() => { createApp(fixture); diff --git a/spec/frontend/gitlab_version_check/mock_data.js b/spec/frontend/gitlab_version_check/mock_data.js index 707d45550eb..fb8c9ec81a7 100644 --- a/spec/frontend/gitlab_version_check/mock_data.js +++ b/spec/frontend/gitlab_version_check/mock_data.js @@ -9,12 +9,6 @@ export const VERSION_CHECK_BADGE_FINDER = '[data-testid="badge-click-wrapper"]'; export const VERSION_BADGE_TEXT = 'Up to date'; -export const SECURITY_PATCH_FIXTURE = `<div id="js-security-patch-upgrade-alert" data-current-version="15.1"></div>`; - -export const SECURITY_PATCH_FINDER = 'h2'; - -export const SECURITY_PATCH_TEXT = 'Critical security upgrade available'; - export const SECURITY_MODAL_FIXTURE = `<div id="js-security-patch-upgrade-alert-modal" data-current-version="15.1" data-version='{ "details": "test details", "latest-stable-versions": "[]" }'></div>`; export const SECURITY_MODAL_FINDER = '[data-testid="alert-modal-title"]'; diff --git a/spec/frontend/token_access/inbound_token_access_spec.js b/spec/frontend/token_access/inbound_token_access_spec.js new file mode 100644 index 00000000000..fcd1a33fa68 --- /dev/null +++ b/spec/frontend/token_access/inbound_token_access_spec.js @@ -0,0 +1,311 @@ +import { GlAlert, GlFormInput, GlToggle, GlLoadingIcon } from '@gitlab/ui'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import { createAlert } from '~/flash'; +import InboundTokenAccess from '~/token_access/components/inbound_token_access.vue'; +import inboundAddProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_add_project_ci_job_token_scope.mutation.graphql'; +import inboundRemoveProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_remove_project_ci_job_token_scope.mutation.graphql'; +import inboundUpdateCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_update_ci_job_token_scope.mutation.graphql'; +import inboundGetCIJobTokenScopeQuery from '~/token_access/graphql/queries/inbound_get_ci_job_token_scope.query.graphql'; +import inboundGetProjectsWithCIJobTokenScopeQuery from '~/token_access/graphql/queries/inbound_get_projects_with_ci_job_token_scope.query.graphql'; +import { + inboundJobTokenScopeEnabledResponse, + inboundJobTokenScopeDisabledResponse, + inboundProjectsWithScopeResponse, + inboundAddProjectSuccessResponse, + inboundRemoveProjectSuccess, + inboundUpdateScopeSuccessResponse, +} from './mock_data'; + +const projectPath = 'root/my-repo'; +const message = 'An error occurred'; +const error = new Error(message); + +Vue.use(VueApollo); + +jest.mock('~/flash'); + +describe('TokenAccess component', () => { + let wrapper; + + const inboundJobTokenScopeEnabledResponseHandler = jest + .fn() + .mockResolvedValue(inboundJobTokenScopeEnabledResponse); + const inboundJobTokenScopeDisabledResponseHandler = jest + .fn() + .mockResolvedValue(inboundJobTokenScopeDisabledResponse); + const inboundProjectsWithScopeResponseHandler = jest + .fn() + .mockResolvedValue(inboundProjectsWithScopeResponse); + const inboundAddProjectSuccessResponseHandler = jest + .fn() + .mockResolvedValue(inboundAddProjectSuccessResponse); + const inboundRemoveProjectSuccessHandler = jest + .fn() + .mockResolvedValue(inboundRemoveProjectSuccess); + const inboundUpdateScopeSuccessResponseHandler = jest + .fn() + .mockResolvedValue(inboundUpdateScopeSuccessResponse); + const failureHandler = jest.fn().mockRejectedValue(error); + + const findToggle = () => wrapper.findComponent(GlToggle); + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findAddProjectBtn = () => wrapper.findByRole('button', { name: 'Add project' }); + const findCancelBtn = () => wrapper.findByRole('button', { name: 'Cancel' }); + const findProjectInput = () => wrapper.findComponent(GlFormInput); + const findRemoveProjectBtn = () => wrapper.findByRole('button', { name: 'Remove access' }); + const findTokenDisabledAlert = () => wrapper.findComponent(GlAlert); + + const createMockApolloProvider = (requestHandlers) => { + return createMockApollo(requestHandlers); + }; + + const createComponent = (requestHandlers, mountFn = shallowMountExtended) => { + wrapper = mountFn(InboundTokenAccess, { + provide: { + fullPath: projectPath, + }, + apolloProvider: createMockApolloProvider(requestHandlers), + data() { + return { + targetProjectPath: 'root/test', + }; + }, + }); + }; + + describe('loading state', () => { + it('shows loading state while waiting on query to resolve', async () => { + createComponent([ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ]); + + expect(findLoadingIcon().exists()).toBe(true); + + await waitForPromises(); + + expect(findLoadingIcon().exists()).toBe(false); + }); + }); + + describe('fetching projects and scope', () => { + it('fetches projects and scope correctly', () => { + const expectedVariables = { + fullPath: 'root/my-repo', + }; + + createComponent([ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ]); + + expect(inboundJobTokenScopeEnabledResponseHandler).toHaveBeenCalledWith(expectedVariables); + expect(inboundProjectsWithScopeResponseHandler).toHaveBeenCalledWith(expectedVariables); + }); + + it('handles fetch projects error correctly', async () => { + createComponent([ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, failureHandler], + ]); + + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith({ + message: 'There was a problem fetching the projects', + }); + }); + + it('handles fetch scope error correctly', async () => { + createComponent([ + [inboundGetCIJobTokenScopeQuery, failureHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ]); + + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith({ + message: 'There was a problem fetching the job token scope value', + }); + }); + }); + + describe('toggle', () => { + it('the toggle is on and the alert is hidden', async () => { + createComponent([ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ]); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(true); + expect(findTokenDisabledAlert().exists()).toBe(false); + }); + + it('the toggle is off and the alert is visible', async () => { + createComponent([ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeDisabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ]); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(false); + expect(findTokenDisabledAlert().exists()).toBe(true); + }); + + describe('update ci job token scope', () => { + it('calls inboundUpdateCIJobTokenScopeMutation mutation', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundUpdateCIJobTokenScopeMutation, inboundUpdateScopeSuccessResponseHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(true); + + findToggle().vm.$emit('change', false); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(false); + expect(inboundUpdateScopeSuccessResponseHandler).toHaveBeenCalledWith({ + input: { + fullPath: 'root/my-repo', + inboundJobTokenScopeEnabled: false, + }, + }); + }); + + it('handles update scope error correctly', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeDisabledResponseHandler], + [inboundUpdateCIJobTokenScopeMutation, failureHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(false); + + findToggle().vm.$emit('change', true); + + await waitForPromises(); + + expect(findToggle().props('value')).toBe(false); + expect(createAlert).toHaveBeenCalledWith({ message }); + }); + }); + }); + + describe('add project', () => { + it('calls add project mutation', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + [inboundAddProjectCIJobTokenScopeMutation, inboundAddProjectSuccessResponseHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + findAddProjectBtn().trigger('click'); + + expect(inboundAddProjectSuccessResponseHandler).toHaveBeenCalledWith({ + projectPath, + targetProjectPath: 'root/test', + }); + }); + + it('add project handles error correctly', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + [inboundAddProjectCIJobTokenScopeMutation, failureHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + findAddProjectBtn().trigger('click'); + + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith({ message }); + }); + + it('clicking cancel clears target path', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + expect(findProjectInput().element.value).toBe('root/test'); + + await findCancelBtn().trigger('click'); + + expect(findProjectInput().element.value).toBe(''); + }); + }); + + describe('remove project', () => { + it('calls remove project mutation', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + [inboundRemoveProjectCIJobTokenScopeMutation, inboundRemoveProjectSuccessHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + findRemoveProjectBtn().trigger('click'); + + expect(inboundRemoveProjectSuccessHandler).toHaveBeenCalledWith({ + projectPath, + targetProjectPath: 'root/ci-project', + }); + }); + + it('remove project handles error correctly', async () => { + createComponent( + [ + [inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler], + [inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler], + [inboundRemoveProjectCIJobTokenScopeMutation, failureHandler], + ], + mountExtended, + ); + + await waitForPromises(); + + findRemoveProjectBtn().trigger('click'); + + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith({ message }); + }); + }); +}); diff --git a/spec/frontend/token_access/mock_data.js b/spec/frontend/token_access/mock_data.js index fff5a0ad4d0..ab04735b985 100644 --- a/spec/frontend/token_access/mock_data.js +++ b/spec/frontend/token_access/mock_data.js @@ -106,6 +106,21 @@ export const mockProjects = [ }, ]; +export const mockFields = [ + { + key: 'project', + label: 'Project with access', + }, + { + key: 'namespace', + label: 'Namespace', + }, + { + key: 'actions', + label: '', + }, +]; + export const optInJwtQueryResponse = (optInJwt) => ({ data: { project: { @@ -131,3 +146,84 @@ export const optInJwtMutationResponse = (optInJwt) => ({ }, }, }); + +export const inboundJobTokenScopeEnabledResponse = { + data: { + project: { + id: '1', + ciCdSettings: { + inboundJobTokenScopeEnabled: true, + __typename: 'ProjectCiCdSetting', + }, + __typename: 'Project', + }, + }, +}; + +export const inboundJobTokenScopeDisabledResponse = { + data: { + project: { + id: '1', + ciCdSettings: { + inboundJobTokenScopeEnabled: false, + __typename: 'ProjectCiCdSetting', + }, + __typename: 'Project', + }, + }, +}; + +export const inboundProjectsWithScopeResponse = { + data: { + project: { + __typename: 'Project', + id: '1', + ciJobTokenScope: { + __typename: 'CiJobTokenScopeType', + inboundAllowlist: { + __typename: 'ProjectConnection', + nodes: [ + { + __typename: 'Project', + fullPath: 'root/ci-project', + id: 'gid://gitlab/Project/23', + name: 'ci-project', + namespace: { id: 'gid://gitlab/Namespaces::UserNamespace/1', fullPath: 'root' }, + }, + ], + }, + }, + }, + }, +}; + +export const inboundAddProjectSuccessResponse = { + data: { + ciJobTokenScopeAddProject: { + errors: [], + __typename: 'CiJobTokenScopeAddProjectPayload', + }, + }, +}; + +export const inboundRemoveProjectSuccess = { + data: { + ciJobTokenScopeRemoveProject: { + errors: [], + __typename: 'CiJobTokenScopeRemoveProjectPayload', + }, + }, +}; + +export const inboundUpdateScopeSuccessResponse = { + data: { + ciCdSettingsUpdate: { + ciCdSettings: { + inboundJobTokenScopeEnabled: false, + __typename: 'ProjectCiCdSetting', + }, + errors: [], + __typename: 'CiCdSettingsUpdatePayload', + }, + }, +}; diff --git a/spec/frontend/token_access/token_access_spec.js b/spec/frontend/token_access/outbound_token_access_spec.js index 62f546463a1..893a021197f 100644 --- a/spec/frontend/token_access/token_access_spec.js +++ b/spec/frontend/token_access/outbound_token_access_spec.js @@ -5,8 +5,7 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/flash'; -import OptInJwt from '~/token_access/components/opt_in_jwt.vue'; -import TokenAccess from '~/token_access/components/token_access.vue'; +import OutboundTokenAccess from '~/token_access/components/outbound_token_access.vue'; import addProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/add_project_ci_job_token_scope.mutation.graphql'; import removeProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/remove_project_ci_job_token_scope.mutation.graphql'; import updateCIJobTokenScopeMutation from '~/token_access/graphql/mutations/update_ci_job_token_scope.mutation.graphql'; @@ -41,7 +40,6 @@ describe('TokenAccess component', () => { const failureHandler = jest.fn().mockRejectedValue(error); const findToggle = () => wrapper.findComponent(GlToggle); - const findOptInJwt = () => wrapper.findComponent(OptInJwt); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findAddProjectBtn = () => wrapper.findByRole('button', { name: 'Add project' }); const findRemoveProjectBtn = () => wrapper.findByRole('button', { name: 'Remove access' }); @@ -52,7 +50,7 @@ describe('TokenAccess component', () => { }; const createComponent = (requestHandlers, mountFn = shallowMountExtended) => { - wrapper = mountFn(TokenAccess, { + wrapper = mountFn(OutboundTokenAccess, { provide: { fullPath: projectPath, }, @@ -65,10 +63,6 @@ describe('TokenAccess component', () => { }); }; - afterEach(() => { - wrapper.destroy(); - }); - describe('loading state', () => { it('shows loading state while waiting on query to resolve', async () => { createComponent([ @@ -84,21 +78,6 @@ describe('TokenAccess component', () => { }); }); - describe('template', () => { - beforeEach(async () => { - createComponent([ - [getCIJobTokenScopeQuery, enabledJobTokenScopeHandler], - [getProjectsWithCIJobTokenScopeQuery, getProjectsWithScopeHandler], - ]); - - await waitForPromises(); - }); - - it('renders the opt in jwt component', () => { - expect(findOptInJwt().exists()).toBe(true); - }); - }); - describe('fetching projects and scope', () => { it('fetches projects and scope correctly', () => { const expectedVariables = { diff --git a/spec/frontend/token_access/token_access_app_spec.js b/spec/frontend/token_access/token_access_app_spec.js new file mode 100644 index 00000000000..7f269ee5fda --- /dev/null +++ b/spec/frontend/token_access/token_access_app_spec.js @@ -0,0 +1,47 @@ +import { shallowMount } from '@vue/test-utils'; +import OutboundTokenAccess from '~/token_access/components/outbound_token_access.vue'; +import InboundTokenAccess from '~/token_access/components/inbound_token_access.vue'; +import OptInJwt from '~/token_access/components/opt_in_jwt.vue'; +import TokenAccessApp from '~/token_access/components/token_access_app.vue'; + +describe('TokenAccessApp component', () => { + let wrapper; + + const findOutboundTokenAccess = () => wrapper.findComponent(OutboundTokenAccess); + const findInboundTokenAccess = () => wrapper.findComponent(InboundTokenAccess); + const findOptInJwt = () => wrapper.findComponent(OptInJwt); + + const createComponent = (flagState = false) => { + wrapper = shallowMount(TokenAccessApp, { + provide: { + glFeatures: { ciInboundJobTokenScope: flagState }, + }, + }); + }; + + describe('default', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders the opt in jwt component', () => { + expect(findOptInJwt().exists()).toBe(true); + }); + + it('renders the outbound token access component', () => { + expect(findOutboundTokenAccess().exists()).toBe(true); + }); + + it('does not render the inbound token access component', () => { + expect(findInboundTokenAccess().exists()).toBe(false); + }); + }); + + describe('with feature flag enabled', () => { + it('renders the inbound token access component', () => { + createComponent(true); + + expect(findInboundTokenAccess().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/token_access/token_projects_table_spec.js b/spec/frontend/token_access/token_projects_table_spec.js index 0fa1a2453f7..b51d8b3ccea 100644 --- a/spec/frontend/token_access/token_projects_table_spec.js +++ b/spec/frontend/token_access/token_projects_table_spec.js @@ -1,7 +1,7 @@ import { GlTable, GlButton } from '@gitlab/ui'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import TokenProjectsTable from '~/token_access/components/token_projects_table.vue'; -import { mockProjects } from './mock_data'; +import { mockProjects, mockFields } from './mock_data'; describe('Token projects table', () => { let wrapper; @@ -12,6 +12,7 @@ describe('Token projects table', () => { fullPath: 'root/ci-project', }, propsData: { + tableFields: mockFields, projects: mockProjects, }, }); @@ -28,10 +29,6 @@ describe('Token projects table', () => { createComponent(); }); - afterEach(() => { - wrapper.destroy(); - }); - it('displays a table', () => { expect(findTable().exists()).toBe(true); }); diff --git a/spec/helpers/version_check_helper_spec.rb b/spec/helpers/version_check_helper_spec.rb index c76eb08820a..1c8eacf088a 100644 --- a/spec/helpers/version_check_helper_spec.rb +++ b/spec/helpers/version_check_helper_spec.rb @@ -49,26 +49,29 @@ RSpec.describe VersionCheckHelper do describe '#show_security_patch_upgrade_alert?' do describe 'return conditions' do - where(:feature_enabled, :show_version_check, :gitlab_version_check, :result) do + where(:show_version_check, :gitlab_version_check, :result) do [ - [false, false, nil, false], - [false, false, { "severity" => "success" }, false], - [false, false, { "severity" => "danger" }, false], - [false, true, nil, false], - [false, true, { "severity" => "success" }, false], - [false, true, { "severity" => "danger" }, false], - [true, false, nil, false], - [true, false, { "severity" => "success" }, false], - [true, false, { "severity" => "danger" }, false], - [true, true, nil, false], - [true, true, { "severity" => "success" }, false], - [true, true, { "severity" => "danger" }, true] + [false, nil, false], + [false, { "severity" => "success" }, false], + [false, { "severity" => "danger" }, false], + [false, { "severity" => "danger", "critical_vulnerability" => 'some text' }, false], + [false, { "severity" => "danger", "critical_vulnerability" => 'false' }, false], + [false, { "severity" => "danger", "critical_vulnerability" => false }, false], + [false, { "severity" => "danger", "critical_vulnerability" => 'true' }, false], + [false, { "severity" => "danger", "critical_vulnerability" => true }, false], + [true, nil, false], + [true, { "severity" => "success" }, nil], + [true, { "severity" => "danger" }, nil], + [true, { "severity" => "danger", "critical_vulnerability" => 'some text' }, nil], + [true, { "severity" => "danger", "critical_vulnerability" => 'false' }, false], + [true, { "severity" => "danger", "critical_vulnerability" => false }, false], + [true, { "severity" => "danger", "critical_vulnerability" => 'true' }, true], + [true, { "severity" => "danger", "critical_vulnerability" => true }, true] ] end with_them do before do - stub_feature_flags(critical_security_alert: feature_enabled) allow(helper).to receive(:show_version_check?).and_return(show_version_check) allow(helper).to receive(:gitlab_version_check).and_return(gitlab_version_check) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index e9de636bb0d..f3a8a9cded3 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2775,16 +2775,6 @@ RSpec.describe Repository, feature_category: :source_code_management do it 'returns a Tree' do expect(repository.head_tree).to be_an_instance_of(Tree) end - - context 'when feature flag "optimized_head_tree" is disabled' do - before do - stub_feature_flags(optimized_head_tree: false) - end - - it 'returns a Tree' do - expect(repository.head_tree).to be_an_instance_of(Tree) - end - end end context 'with a non-existing repository' do @@ -2793,18 +2783,6 @@ RSpec.describe Repository, feature_category: :source_code_management do expect(repository.head_tree).to be_nil end - - context 'when feature flag "optimized_head_tree" is disabled' do - before do - stub_feature_flags(optimized_head_tree: false) - end - - it 'returns nil' do - expect(repository).to receive(:head_commit).and_return(nil) - - expect(repository.head_tree).to be_nil - end - end end end @@ -2817,33 +2795,16 @@ RSpec.describe Repository, feature_category: :source_code_management do let(:pagination_params) { nil } context 'using a non-existing repository' do - context 'when feature flag "optimized_head_tree" is enabled' do - before do - allow(repository).to receive(:root_ref).and_return(nil) - end - - it { is_expected.to be_nil } - - context 'when path is defined' do - let(:path) { 'README.md' } - - it { is_expected.to be_nil } - end + before do + allow(repository).to receive(:root_ref).and_return(nil) end - context 'when feature flag "optimized_head_tree" is disabled' do - before do - stub_feature_flags(optimized_head_tree: false) - allow(repository).to receive(:head_commit).and_return(nil) - end - - it { is_expected.to be_nil } + it { is_expected.to be_nil } - context 'when path is defined' do - let(:path) { 'README.md' } + context 'when path is defined' do + let(:path) { 'README.md' } - it { is_expected.to be_nil } - end + it { is_expected.to be_nil } end end diff --git a/spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb b/spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb index 4387a3f5b07..c94511a0c82 100644 --- a/spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb +++ b/spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb @@ -9,10 +9,6 @@ RSpec.describe 'shared/gitlab_version/_security_patch_upgrade_alert' do render end - it 'renders the security patch upgrade alert' do - expect(rendered).to have_selector('#js-security-patch-upgrade-alert') - end - it 'renders the security patch upgrade alert modal' do expect(rendered).to have_selector('#js-security-patch-upgrade-alert-modal') end |