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
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/test-on-gdk/main.gitlab-ci.yml2
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue4
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue2
-rw-r--r--app/assets/javascripts/super_sidebar/components/pinned_section.vue9
-rw-r--r--app/assets/javascripts/super_sidebar/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue12
-rw-r--r--config/feature_flags/development/sync_approval_rules_from_findings.yml (renamed from config/feature_flags/development/import_project_from_remote_file_s3.yml)10
-rw-r--r--config/initializers/carrierwave_patch.rb2
-rw-r--r--doc/api/graphql/reference/index.md19
-rw-r--r--doc/api/project_import_export.md4
-rw-r--r--doc/architecture/blueprints/secret_detection/index.md34
-rw-r--r--doc/development/sec/security_report_ingestion_overview.md10
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--locale/gitlab.pot3
-rwxr-xr-xqa/gdk/launch2
-rw-r--r--spec/features/nav/pinned_nav_items_spec.rb20
-rw-r--r--spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap2
-rw-r--r--spec/frontend/design_management/components/toolbar/design_navigation_spec.js62
-rw-r--r--spec/frontend/design_management/mock_data/apollo_mock.js84
-rw-r--r--spec/frontend/super_sidebar/components/pinned_section_spec.js75
-rw-r--r--spec/requests/api/project_import_spec.rb86
-rw-r--r--workhorse/Makefile3
22 files changed, 287 insertions, 163 deletions
diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
index a04d81fb342..d51e255fb95 100644
--- a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
+++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
@@ -57,7 +57,7 @@ dont-interrupt-me:
--volume $CI_PROJECT_DIR/test_output:/home/gdk/gdk/gitlab/qa/tmp:z \
--volume $CI_PROJECT_DIR/logs/gdk:/home/gdk/gdk/log \
--volume $CI_PROJECT_DIR/logs/gitlab:/home/gdk/gdk/gitlab/log \
- ${QA_GDK_IMAGE} "${CI_COMMIT_REF_SLUG}" "$TEST_GDK_TAGS --tag ~requires_praefect" || true
+ ${QA_GDK_IMAGE} "${CI_COMMIT_SHA}" "$TEST_GDK_TAGS --tag ~requires_praefect" || true
- echo -e "\e[0Ksection_end:`date +%s`:launch_gdk_and_tests\r\e[0K"
allow_failure: true
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 21841680cab..9c04a72375b 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -35,9 +35,6 @@ export default {
isAuthoredByMe() {
return this.noteAuthorId === this.getUserData.id;
},
- addButtonClass() {
- return this.isAuthoredByMe ? 'js-user-authored' : '';
- },
},
methods: {
...mapActions(['toggleAwardRequest']),
@@ -64,7 +61,6 @@ export default {
:awards="awards"
:can-award-emoji="canAwardEmoji"
:current-user-id="getUserData.id"
- :add-button-class="addButtonClass"
@award="handleAward($event)"
/>
</div>
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 60df042529a..4ce714f7c21 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -144,7 +144,7 @@ export default {
},
computed: {
shouldRenderGenie() {
- return this.glFeatures.explainCode && this.glFeatures.explainCodeSnippet;
+ return this.glFeatures.explainCode && this.glFeatures.explainCodeSnippet && this.isLoggedIn;
},
isLoggedIn() {
return isLoggedIn();
diff --git a/app/assets/javascripts/super_sidebar/components/pinned_section.vue b/app/assets/javascripts/super_sidebar/components/pinned_section.vue
index 193de143c2b..164ea04ab8e 100644
--- a/app/assets/javascripts/super_sidebar/components/pinned_section.vue
+++ b/app/assets/javascripts/super_sidebar/components/pinned_section.vue
@@ -2,6 +2,8 @@
import { GlCollapse, GlIcon } from '@gitlab/ui';
import Draggable from 'vuedraggable';
import { s__ } from '~/locale';
+import { setCookie, getCookie } from '~/lib/utils/common_utils';
+import { SIDEBAR_PINS_EXPANDED_COOKIE, SIDEBAR_COOKIE_EXPIRATION } from '../constants';
import NavItem from './nav_item.vue';
export default {
@@ -25,7 +27,7 @@ export default {
},
data() {
return {
- expanded: true,
+ expanded: getCookie(SIDEBAR_PINS_EXPANDED_COOKIE) !== 'false',
draggableItems: this.items,
};
},
@@ -38,6 +40,11 @@ export default {
},
},
watch: {
+ expanded(newExpanded) {
+ setCookie(SIDEBAR_PINS_EXPANDED_COOKIE, newExpanded, {
+ expires: SIDEBAR_COOKIE_EXPIRATION,
+ });
+ },
items(newItems) {
this.draggableItems = newItems;
},
diff --git a/app/assets/javascripts/super_sidebar/constants.js b/app/assets/javascripts/super_sidebar/constants.js
index 4e25b9cff45..3dbd12b4ff7 100644
--- a/app/assets/javascripts/super_sidebar/constants.js
+++ b/app/assets/javascripts/super_sidebar/constants.js
@@ -30,3 +30,6 @@ export const HELP_MENU_TRACKING_DEFAULTS = {
'data-track-property': 'nav_help_menu',
'data-track-action': 'click_link',
};
+
+export const SIDEBAR_PINS_EXPANDED_COOKIE = 'sidebar_pinned_section_expanded';
+export const SIDEBAR_COOKIE_EXPIRATION = 365 * 10;
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index cb38b3e13bb..8f1f7ba0ad8 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -35,11 +35,6 @@ export default {
required: false,
default: NO_USER_ID,
},
- addButtonClass: {
- type: String,
- required: false,
- default: '',
- },
defaultAwards: {
type: Array,
required: false,
@@ -50,6 +45,11 @@ export default {
required: false,
default: 'selected',
},
+ boundary: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -201,6 +201,8 @@ export default {
v-gl-tooltip.viewport
:title="__('Add reaction')"
:toggle-class="['add-reaction-button btn-icon gl-relative!', { 'is-active': isMenuOpen }]"
+ :right="false"
+ :boundary="boundary"
data-testid="emoji-picker"
@click="handleAward"
@shown="setIsMenuOpen(true)"
diff --git a/config/feature_flags/development/import_project_from_remote_file_s3.yml b/config/feature_flags/development/sync_approval_rules_from_findings.yml
index c7d52202726..e09593b17a6 100644
--- a/config/feature_flags/development/import_project_from_remote_file_s3.yml
+++ b/config/feature_flags/development/sync_approval_rules_from_findings.yml
@@ -1,8 +1,8 @@
---
-name: import_project_from_remote_file_s3
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77259
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350571
-milestone: '14.9'
+name: sync_approval_rules_from_findings
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115825
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/397011
+milestone: '15.11'
type: development
-group: group::import
+group: group::security policies
default_enabled: false
diff --git a/config/initializers/carrierwave_patch.rb b/config/initializers/carrierwave_patch.rb
index cb476d9f01a..449f4b4a607 100644
--- a/config/initializers/carrierwave_patch.rb
+++ b/config/initializers/carrierwave_patch.rb
@@ -22,7 +22,7 @@ module CarrierWave
# multithreaded uploads (https://github.com/fog/fog-aws/pull/579).
# Multithreaded uploads are essential for copying large amounts of data
# within the request timeout.
- if ::Feature.enabled?(:s3_multithreaded_uploads) && fog_provider == 'AWS'
+ if ::Feature.enabled?(:s3_multithreaded_uploads, type: :ops) && fog_provider == 'AWS'
# AWS SDK uses 10 threads by default and a multipart chunk size of 10 MB
file.concurrency = 10
file.multipart_chunk_size = 10485760
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index c97f920af3d..e6d88904341 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -959,6 +959,7 @@ Input type: `AiActionInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationaiactionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationaiactionexplaincode"></a>`explainCode` | [`AiExplainCodeInput`](#aiexplaincodeinput) | Input for explain_code AI action. |
| <a id="mutationaiactionsummarizecomments"></a>`summarizeComments` | [`AiSummarizeCommentsInput`](#aisummarizecommentsinput) | Input for summarize_comments AI action. |
#### Fields
@@ -26480,6 +26481,24 @@ be used as arguments).
Only general use input types are listed here. For mutation input types,
see the associated mutation type above.
+### `AiExplainCodeInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="aiexplaincodeinputmessages"></a>`messages` | [`[AiExplainCodeMessageInput!]!`](#aiexplaincodemessageinput) | Code messages that is passed to be explained by AI. |
+| <a id="aiexplaincodeinputresourceid"></a>`resourceId` | [`AiModelID!`](#aimodelid) | GID of the resource to mutate. |
+
+### `AiExplainCodeMessageInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="aiexplaincodemessageinputcontent"></a>`content` | [`String!`](#string) | Content of the message. |
+| <a id="aiexplaincodemessageinputrole"></a>`role` | [`String!`](#string) | Role of the message (system, user, assistant). |
+
### `AiSummarizeCommentsInput`
#### Arguments
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 22df2b2ef4a..0e52bb959cb 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -255,9 +255,7 @@ The `Content-Type` header must be `application/gzip`.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348874) in GitLab 14.9 in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta), [with a flag](../administration/feature_flags.md) named `import_project_from_remote_file_s3`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/348874) in GitLab 14.10.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `import_project_from_remote_file_s3`. On GitLab.com, this feature is available.
+> - [Enabled globally](https://gitlab.com/gitlab-org/gitlab/-/issues/350571) in GitLab 15.11.
```plaintext
POST /projects/remote-import-s3
diff --git a/doc/architecture/blueprints/secret_detection/index.md b/doc/architecture/blueprints/secret_detection/index.md
index 9911fd04667..de240646b37 100644
--- a/doc/architecture/blueprints/secret_detection/index.md
+++ b/doc/architecture/blueprints/secret_detection/index.md
@@ -170,20 +170,20 @@ sequenceDiagram
## Iterations
-- [x] Define [requirements for detection coverage and actions](https://gitlab.com/gitlab-org/gitlab/-/issues/376716)
-- [x] Implement [Clientside detection of GitLab tokens within comments/issues](https://gitlab.com/gitlab-org/gitlab/-/issues/368434)
-- [ ] PoC of secret scanning service
- - [ ] Benchmarking of issuables, comments, job logs and blobs to gain confidence that the total costs will be viable
- - [ ] Capacity planning for addition of service component to Reference Architectures headroom
- - [ ] Service capabilities
- - [ ] gRPC commit retrieval from Gitaly
- - [ ] blob scanning
-- [ ] Implementation of secret scanning service MVC (targeting individual commits)
-- [ ] Security and readiness review
-- [ ] Deployment and monitoring
-- [ ] Implementation of secret scanning service MVC (targeting arbitrary text blobs)
-- [ ] Deployment and monitoring
-- [ ] High priority domain object rollout (priority `TBD`)
- - [ ] Issuable comments
- - [ ] Issuable bodies
- - [ ] Job logs
+- ✓ Define [requirements for detection coverage and actions](https://gitlab.com/gitlab-org/gitlab/-/issues/376716)
+- ✓ Implement [Clientside detection of GitLab tokens within comments/issues](https://gitlab.com/gitlab-org/gitlab/-/issues/368434)
+- PoC of secret scanning service
+ - Benchmarking of issuables, comments, job logs and blobs to gain confidence that the total costs will be viable
+ - Capacity planning for addition of service component to Reference Architectures headroom
+ - Service capabilities
+ - gRPC commit retrieval from Gitaly
+ - blob scanning
+- Implementation of secret scanning service MVC (targeting individual commits)
+- Security and readiness review
+- Deployment and monitoring
+- Implementation of secret scanning service MVC (targeting arbitrary text blobs)
+- Deployment and monitoring
+- High priority domain object rollout (priority `TBD`)
+ - Issuable comments
+ - Issuable bodies
+ - Job logs
diff --git a/doc/development/sec/security_report_ingestion_overview.md b/doc/development/sec/security_report_ingestion_overview.md
index 492d840e800..aca33990b0f 100644
--- a/doc/development/sec/security_report_ingestion_overview.md
+++ b/doc/development/sec/security_report_ingestion_overview.md
@@ -12,7 +12,7 @@ The `Vulnerability::Feedback` model is currently undergoing deprecation and shou
## Commonly used terms
-### Feedback
+### Feedback
An instance of `Vulnerabilities::Feedback` class. They are created to keep track of users' interactions with Vulnerability Findings before they are promoted to a Vulnerability. This model is deprecated and due to be removed by GitLab 16.0 as part of the [Deprecate and remove Vulnerabilities::Feedback epic](https://gitlab.com/groups/gitlab-org/-/epics/5629).
@@ -38,7 +38,7 @@ An instance of the `Vulnerabilities::StateTransition` class. This model represen
### Vulnerability
-An instance of `Vulnerability` class. A `Vulnerability` is representative of a `Vulnerability::Finding` which has been detected in the default branch of the project, or if the `present_on_default_branch` flag is false, is representative of a finding which has been interacted with in some way outside of the default branch, such as if it is dismissed (`State Transition`), or linked to an `Issue` or `Merge Request`. They are created based on information available in `Vulnerabilities::Finding` class. Every `Vulnerability` **must have** a corresponding `Vulnerabilities::Finding` object to be valid, however this is not enforced at the database level.
+An instance of `Vulnerability` class. A `Vulnerability` is representative of a `Vulnerability::Finding` which has been detected in the default branch of the project, or if the `present_on_default_branch` flag is false, is representative of a finding which has been interacted with in some way outside of the default branch, such as if it is dismissed (`State Transition`), or linked to an `Issue` or `Merge Request`. They are created based on information available in `Vulnerabilities::Finding` class. Every `Vulnerability` **must have** a corresponding `Vulnerabilities::Finding` object to be valid, however this is not enforced at the database level.
### Finding
@@ -81,7 +81,7 @@ At this point, the following things can happen to the `Security::Finding` which
### Scan runs in a pipeline for the default branch
-If the pipeline ran on the default branch then the following steps, in addition to the steps in [#scan-runs-in-a-pipeline-for-a-non-default-branch], are executed:
+If the pipeline ran on the default branch then the following steps, in addition to the steps in [Scan runs in a pipeline for a non-default branch](#scan-runs-in-a-pipeline-for-a-non-default-branch), are executed:
1. `Security::StoreScansService` gets called and schedules `StoreSecurityReportsWorker`.
1. `StoreSecurityReportsWorker` executes `Security::Ingestion::IngestReportsService`.
@@ -92,8 +92,8 @@ If the pipeline ran on the default branch then the following steps, in addition
If you change the state of a vulnerability, such as selecting `Dismiss vulnerability` the following things currently happen:
-- A `Feedback` record of `dismissal` type is created to record the current state.
-- If they do not already exist, a `Vulnerability Finding` and a `Vulnerability` with `present_on_default_branch: false` attribute get created, to which a `State Transition` reflecting the state change is related.
+- A `Feedback` record of `dismissal` type is created to record the current state.
+- If they do not already exist, a `Vulnerability Finding` and a `Vulnerability` with `present_on_default_branch: false` attribute get created, to which a `State Transition` reflecting the state change is related.
You can optionally add a comment to the state change which is recorded on both the `Feedback` and the `State Transition`.
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 02f0d9a2a70..a00ef7144d4 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -217,8 +217,6 @@ module API
]
end
post 'remote-import-s3' do
- not_found! unless ::Feature.enabled?(:import_project_from_remote_file_s3)
-
check_rate_limit! :project_import, scope: [current_user, :project_import]
response = ::Import::GitlabProjects::CreateProjectService.new(
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 10536863947..e8e6a120c77 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1863,6 +1863,9 @@ msgstr ""
msgid "AI|What does the selected code mean?"
msgstr ""
+msgid "AI|You are not allowed to copy any part of this output into issues, comments, GitLab source code, commit messages, merge requests or any other user interface in the %{gitlabOrg} or %{gitlabCom} groups."
+msgstr ""
+
msgid "API"
msgstr ""
diff --git a/qa/gdk/launch b/qa/gdk/launch
index 4b1fc6ae191..8ad2ce7e5ad 100755
--- a/qa/gdk/launch
+++ b/qa/gdk/launch
@@ -1,6 +1,6 @@
#!/bin/bash
-COMMIT_REF=${1:-$CI_COMMIT_REF_SLUG}
+COMMIT_REF=${1:-$CI_COMMIT_SHA}
RSPEC_ARGS=$2
if [ -z "${COMMIT_REF}" ]; then
diff --git a/spec/features/nav/pinned_nav_items_spec.rb b/spec/features/nav/pinned_nav_items_spec.rb
index b4eea931857..fa8224848f9 100644
--- a/spec/features/nav/pinned_nav_items_spec.rb
+++ b/spec/features/nav/pinned_nav_items_spec.rb
@@ -54,6 +54,26 @@ RSpec.describe 'Navigation menu item pinning', :js, feature_category: :navigatio
end
end
+ describe 'collapsible section' do
+ it 'shows the Pinned section as expanded by default' do
+ within '#super-sidebar' do
+ expect(page).to have_content 'Your pinned items appear here.'
+ end
+ end
+
+ it 'maintains the collapsed/expanded state between page loads' do
+ within '#super-sidebar' do
+ click_on 'Pinned'
+ visit project_path(project)
+ expect(page).not_to have_content 'Your pinned items appear here.'
+
+ click_on 'Pinned'
+ visit project_path(project)
+ expect(page).to have_content 'Your pinned items appear here.'
+ end
+ end
+ end
+
describe 'pinned items' do
before do
within '#super-sidebar' do
diff --git a/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap b/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
index b5a69b28a88..934bda570d4 100644
--- a/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
+++ b/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
@@ -7,7 +7,7 @@ exports[`Design management pagination component renders navigation buttons 1`] =
class="gl-display-flex gl-align-items-center"
>
- 0 of 2
+ 0 of 3
<gl-button-group-stub
class="gl-mx-5"
diff --git a/spec/frontend/design_management/components/toolbar/design_navigation_spec.js b/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
index 8427d83ceee..46eb4c16af8 100644
--- a/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
+++ b/spec/frontend/design_management/components/toolbar/design_navigation_spec.js
@@ -1,9 +1,15 @@
/* global Mousetrap */
import 'mousetrap';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlButtonGroup } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
import DesignNavigation from '~/design_management/components/toolbar/design_navigation.vue';
import { DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { designListQueryResponse, designListQueryResponseNodes } from '../../mock_data/apollo_mock';
const push = jest.fn();
const $router = {
@@ -18,11 +24,24 @@ const $route = {
describe('Design management pagination component', () => {
let wrapper;
- function createComponent() {
+ const buildMockHandler = (nodes = designListQueryResponseNodes) => {
+ designListQueryResponse.data.project.issue.designCollection.designs.nodes = nodes;
+ return jest.fn().mockResolvedValue(designListQueryResponse);
+ };
+
+ const createMockApolloProvider = (handler) => {
+ Vue.use(VueApollo);
+
+ return createMockApollo([[getDesignListQuery, handler]]);
+ };
+
+ function createComponent({ propsData = {}, handler = buildMockHandler() } = {}) {
wrapper = shallowMount(DesignNavigation, {
propsData: {
id: '2',
+ ...propsData,
},
+ apolloProvider: createMockApolloProvider(handler),
mocks: {
$router,
$route,
@@ -30,48 +49,45 @@ describe('Design management pagination component', () => {
});
}
- beforeEach(() => {
- createComponent();
- });
+ const findGlButtonGroup = () => wrapper.findComponent(GlButtonGroup);
+
+ it('hides components when designs are empty', async () => {
+ createComponent({ handler: buildMockHandler([]) });
+ await waitForPromises();
- it('hides components when designs are empty', () => {
+ expect(findGlButtonGroup().exists()).toBe(false);
expect(wrapper.element).toMatchSnapshot();
});
it('renders navigation buttons', async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- designCollection: { designs: [{ id: '1' }, { id: '2' }] },
- });
+ createComponent({ handler: buildMockHandler() });
+ await waitForPromises();
- await nextTick();
+ expect(findGlButtonGroup().exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot();
});
describe('keyboard buttons navigation', () => {
- beforeEach(() => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- designCollection: { designs: [{ filename: '1' }, { filename: '2' }, { filename: '3' }] },
- });
- });
+ it('routes to previous design on Left button', async () => {
+ createComponent({ propsData: { id: designListQueryResponseNodes[1].filename } });
+ await waitForPromises();
- it('routes to previous design on Left button', () => {
Mousetrap.trigger('left');
expect(push).toHaveBeenCalledWith({
name: DESIGN_ROUTE_NAME,
- params: { id: '1' },
+ params: { id: designListQueryResponseNodes[0].filename },
query: {},
});
});
- it('routes to next design on Right button', () => {
+ it('routes to next design on Right button', async () => {
+ createComponent({ propsData: { id: designListQueryResponseNodes[1].filename } });
+ await waitForPromises();
+
Mousetrap.trigger('right');
expect(push).toHaveBeenCalledWith({
name: DESIGN_ROUTE_NAME,
- params: { id: '3' },
+ params: { id: designListQueryResponseNodes[2].filename },
query: {},
});
});
diff --git a/spec/frontend/design_management/mock_data/apollo_mock.js b/spec/frontend/design_management/mock_data/apollo_mock.js
index 2b99dcf14da..a7355719141 100644
--- a/spec/frontend/design_management/mock_data/apollo_mock.js
+++ b/spec/frontend/design_management/mock_data/apollo_mock.js
@@ -1,3 +1,45 @@
+export const designListQueryResponseNodes = [
+ {
+ __typename: 'Design',
+ id: '1',
+ event: 'NONE',
+ filename: 'fox_1.jpg',
+ notesCount: 3,
+ image: 'image-1',
+ imageV432x230: 'image-1',
+ currentUserTodos: {
+ __typename: 'ToDo',
+ nodes: [],
+ },
+ },
+ {
+ __typename: 'Design',
+ id: '2',
+ event: 'NONE',
+ filename: 'fox_2.jpg',
+ notesCount: 2,
+ image: 'image-2',
+ imageV432x230: 'image-2',
+ currentUserTodos: {
+ __typename: 'ToDo',
+ nodes: [],
+ },
+ },
+ {
+ __typename: 'Design',
+ id: '3',
+ event: 'NONE',
+ filename: 'fox_3.jpg',
+ notesCount: 1,
+ image: 'image-3',
+ imageV432x230: 'image-3',
+ currentUserTodos: {
+ __typename: 'ToDo',
+ nodes: [],
+ },
+ },
+];
+
export const designListQueryResponse = {
data: {
project: {
@@ -11,47 +53,7 @@ export const designListQueryResponse = {
copyState: 'READY',
designs: {
__typename: 'DesignConnection',
- nodes: [
- {
- __typename: 'Design',
- id: '1',
- event: 'NONE',
- filename: 'fox_1.jpg',
- notesCount: 3,
- image: 'image-1',
- imageV432x230: 'image-1',
- currentUserTodos: {
- __typename: 'ToDo',
- nodes: [],
- },
- },
- {
- __typename: 'Design',
- id: '2',
- event: 'NONE',
- filename: 'fox_2.jpg',
- notesCount: 2,
- image: 'image-2',
- imageV432x230: 'image-2',
- currentUserTodos: {
- __typename: 'ToDo',
- nodes: [],
- },
- },
- {
- __typename: 'Design',
- id: '3',
- event: 'NONE',
- filename: 'fox_3.jpg',
- notesCount: 1,
- image: 'image-3',
- imageV432x230: 'image-3',
- currentUserTodos: {
- __typename: 'ToDo',
- nodes: [],
- },
- },
- ],
+ nodes: designListQueryResponseNodes,
},
versions: {
__typename: 'DesignVersion',
diff --git a/spec/frontend/super_sidebar/components/pinned_section_spec.js b/spec/frontend/super_sidebar/components/pinned_section_spec.js
new file mode 100644
index 00000000000..7ead6a40895
--- /dev/null
+++ b/spec/frontend/super_sidebar/components/pinned_section_spec.js
@@ -0,0 +1,75 @@
+import { nextTick } from 'vue';
+import Cookies from '~/lib/utils/cookies';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import PinnedSection from '~/super_sidebar/components/pinned_section.vue';
+import NavItem from '~/super_sidebar/components/nav_item.vue';
+import { SIDEBAR_PINS_EXPANDED_COOKIE, SIDEBAR_COOKIE_EXPIRATION } from '~/super_sidebar/constants';
+import { setCookie } from '~/lib/utils/common_utils';
+
+jest.mock('~/lib/utils/common_utils', () => ({
+ getCookie: jest.requireActual('~/lib/utils/common_utils').getCookie,
+ setCookie: jest.fn(),
+}));
+
+describe('PinnedSection component', () => {
+ let wrapper;
+
+ const findToggle = () => wrapper.find('a');
+
+ const createWrapper = () => {
+ wrapper = mountExtended(PinnedSection, {
+ propsData: {
+ items: [{ title: 'Pin 1', href: '/page1' }],
+ },
+ });
+ };
+
+ describe('expanded', () => {
+ describe('when cookie is not set', () => {
+ it('is expanded by default', () => {
+ createWrapper();
+ expect(wrapper.findComponent(NavItem).isVisible()).toBe(true);
+ });
+ });
+
+ describe('when cookie is set to false', () => {
+ beforeEach(() => {
+ Cookies.set(SIDEBAR_PINS_EXPANDED_COOKIE, 'false');
+ createWrapper();
+ });
+
+ it('is collapsed', () => {
+ expect(wrapper.findComponent(NavItem).isVisible()).toBe(false);
+ });
+
+ it('updates the cookie when expanding the section', async () => {
+ findToggle().trigger('click');
+ await nextTick();
+
+ expect(setCookie).toHaveBeenCalledWith(SIDEBAR_PINS_EXPANDED_COOKIE, true, {
+ expires: SIDEBAR_COOKIE_EXPIRATION,
+ });
+ });
+ });
+
+ describe('when cookie is set to true', () => {
+ beforeEach(() => {
+ Cookies.set(SIDEBAR_PINS_EXPANDED_COOKIE, 'true');
+ createWrapper();
+ });
+
+ it('is expanded', () => {
+ expect(wrapper.findComponent(NavItem).isVisible()).toBe(true);
+ });
+
+ it('updates the cookie when collapsing the section', async () => {
+ findToggle().trigger('click');
+ await nextTick();
+
+ expect(setCookie).toHaveBeenCalledWith(SIDEBAR_PINS_EXPANDED_COOKIE, false, {
+ expires: SIDEBAR_COOKIE_EXPIRATION,
+ });
+ });
+ });
+ });
+});
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 027c61bb9e1..78b83356675 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -403,63 +403,49 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
it_behaves_like 'requires authentication'
- it 'returns NOT FOUND when the feature is disabled' do
- stub_feature_flags(import_project_from_remote_file_s3: false)
-
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- context 'when the feature flag is enabled' do
- before do
- stub_feature_flags(import_project_from_remote_file_s3: true)
- end
-
- context 'when the response is successful' do
- it 'schedules the import successfully' do
- project = create(
- :project,
- namespace: user.namespace,
- name: 'test-import',
- path: 'test-import'
- )
+ context 'when the response is successful' do
+ it 'schedules the import successfully' do
+ project = create(
+ :project,
+ namespace: user.namespace,
+ name: 'test-import',
+ path: 'test-import'
+ )
- service_response = ServiceResponse.success(payload: project)
- expect_next(::Import::GitlabProjects::CreateProjectService)
- .to receive(:execute)
- .and_return(service_response)
+ service_response = ServiceResponse.success(payload: project)
+ expect_next(::Import::GitlabProjects::CreateProjectService)
+ .to receive(:execute)
+ .and_return(service_response)
- subject
+ subject
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to include({
- 'id' => project.id,
- 'name' => 'test-import',
- 'name_with_namespace' => "#{user.namespace.name} / test-import",
- 'path' => 'test-import',
- 'path_with_namespace' => "#{user.namespace.path}/test-import"
- })
- end
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to include({
+ 'id' => project.id,
+ 'name' => 'test-import',
+ 'name_with_namespace' => "#{user.namespace.name} / test-import",
+ 'path' => 'test-import',
+ 'path_with_namespace' => "#{user.namespace.path}/test-import"
+ })
end
+ end
- context 'when the service returns an error' do
- it 'fails to schedule the import' do
- service_response = ServiceResponse.error(
- message: 'Failed to import',
- http_status: :bad_request
- )
- expect_next(::Import::GitlabProjects::CreateProjectService)
- .to receive(:execute)
- .and_return(service_response)
+ context 'when the service returns an error' do
+ it 'fails to schedule the import' do
+ service_response = ServiceResponse.error(
+ message: 'Failed to import',
+ http_status: :bad_request
+ )
+ expect_next(::Import::GitlabProjects::CreateProjectService)
+ .to receive(:execute)
+ .and_return(service_response)
- subject
+ subject
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response).to eq({
- 'message' => 'Failed to import'
- })
- end
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response).to eq({
+ 'message' => 'Failed to import'
+ })
end
end
end
diff --git a/workhorse/Makefile b/workhorse/Makefile
index ba99276d1be..ac6c5456340 100644
--- a/workhorse/Makefile
+++ b/workhorse/Makefile
@@ -29,8 +29,7 @@ ifeq (${FIPS_MODE}, 1)
export CGO_ENABLED=1
# Go 1.19+ now requires GOEXPERIMENT=boringcrypto for FIPS compilation.
# See https://github.com/golang/go/issues/51940 for more details.
- BORINGCRYPTO_SUPPORT := $(shell GOEXPERIMENT=boringcrypto go version &> /dev/null; echo $$?)
- ifeq ($(BORINGCRYPTO_SUPPORT), 0)
+ ifeq ($(shell GOEXPERIMENT=boringcrypto go version > /dev/null 2>&1; echo $$?), 0)
export GOEXPERIMENT=boringcrypto
endif
endif