Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-09 00:11:09 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-09 00:11:09 +0300
commit3d42e098d9658853984534c9dfc2bf76284a8ac0 (patch)
tree269e9d9e017124f5f6d841311661832ea7e4eff8 /spec
parenta3487798aeff89daff78749e6d6f392d3ca23687 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/explore/groups_controller_spec.rb8
-rw-r--r--spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js15
-rw-r--r--spec/frontend/gitlab_version_check/components/security_patch_upgrade_alert_spec.js84
-rw-r--r--spec/frontend/gitlab_version_check/index_spec.js19
-rw-r--r--spec/frontend/gitlab_version_check/mock_data.js6
-rw-r--r--spec/frontend/token_access/inbound_token_access_spec.js311
-rw-r--r--spec/frontend/token_access/mock_data.js96
-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.js47
-rw-r--r--spec/frontend/token_access/token_projects_table_spec.js7
-rw-r--r--spec/helpers/version_check_helper_spec.rb31
-rw-r--r--spec/models/repository_spec.rb51
-rw-r--r--spec/views/shared/gitlab_version/_security_patch_upgrade_alert.html.haml_spec.rb4
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