Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
11438b1771
commit
fcfafe81d1
|
|
@ -174,7 +174,7 @@ export default {
|
|||
/>
|
||||
</template>
|
||||
<template #default>
|
||||
<board-sidebar-title />
|
||||
<board-sidebar-title data-testid="sidebar-title" />
|
||||
<sidebar-assignees-widget
|
||||
:iid="activeBoardItem.iid"
|
||||
:full-path="fullPath"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
<script>
|
||||
import { GlDisclosureDropdown } from '@gitlab/ui';
|
||||
import { GlBadge, GlButton, GlDisclosureDropdown, GlDisclosureDropdownGroup } from '@gitlab/ui';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import { PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
|
||||
import { __ } from '~/locale';
|
||||
import { STORAGE_KEY } from '~/whats_new/utils/notification';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlBadge,
|
||||
GlButton,
|
||||
GlDisclosureDropdown,
|
||||
GlDisclosureDropdownGroup,
|
||||
},
|
||||
i18n: {
|
||||
help: __('Help'),
|
||||
|
|
@ -27,7 +31,12 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
items: [
|
||||
showWhatsNewNotification: this.shouldShowWhatsNewNotification(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
items() {
|
||||
return [
|
||||
{
|
||||
items: [
|
||||
{ text: this.$options.i18n.help, href: helpPagePath() },
|
||||
|
|
@ -44,23 +53,49 @@ export default {
|
|||
},
|
||||
{
|
||||
items: [
|
||||
{ text: this.$options.i18n.shortcuts, action: this.showKeyboardShortcuts },
|
||||
{
|
||||
text: this.$options.i18n.shortcuts,
|
||||
action: this.showKeyboardShortcuts,
|
||||
shortcut: '?',
|
||||
},
|
||||
this.sidebarData.display_whats_new && {
|
||||
text: this.$options.i18n.whatsnew,
|
||||
action: this.showWhatsNew,
|
||||
count:
|
||||
this.showWhatsNewNotification &&
|
||||
this.sidebarData.whats_new_most_recent_release_items_count,
|
||||
},
|
||||
].filter(Boolean),
|
||||
},
|
||||
],
|
||||
};
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
shouldShowWhatsNewNotification() {
|
||||
if (
|
||||
!this.sidebarData.display_whats_new ||
|
||||
localStorage.getItem(STORAGE_KEY) === this.sidebarData.whats_new_version_digest
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
handleAction({ action }) {
|
||||
if (action) {
|
||||
action();
|
||||
}
|
||||
},
|
||||
|
||||
showKeyboardShortcuts() {
|
||||
this.$refs.dropdown.close();
|
||||
window?.toggleShortcutsHelp();
|
||||
},
|
||||
|
||||
async showWhatsNew() {
|
||||
this.$refs.dropdown.close();
|
||||
this.showWhatsNewNotification = false;
|
||||
|
||||
if (!this.toggleWhatsNewDrawer) {
|
||||
const appEl = document.getElementById('whats-new-app');
|
||||
const { default: toggleWhatsNewDrawer } = await import(
|
||||
|
|
@ -77,12 +112,26 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<gl-disclosure-dropdown
|
||||
ref="dropdown"
|
||||
icon="question-o"
|
||||
:items="items"
|
||||
:toggle-text="$options.i18n.help"
|
||||
category="tertiary"
|
||||
no-caret
|
||||
/>
|
||||
<gl-disclosure-dropdown ref="dropdown">
|
||||
<template #toggle>
|
||||
<gl-button category="tertiary" icon="question-o" class="btn-with-notification">
|
||||
<span v-if="showWhatsNewNotification" class="notification"></span>
|
||||
{{ $options.i18n.help }}
|
||||
</gl-button>
|
||||
</template>
|
||||
|
||||
<gl-disclosure-dropdown-group :group="items[0]" />
|
||||
<gl-disclosure-dropdown-group :group="items[1]" bordered @action="handleAction">
|
||||
<template #list-item="{ item }">
|
||||
<button
|
||||
tabindex="-1"
|
||||
class="gl-bg-transparent gl-w-full gl-border-none gl-display-flex gl-justify-content-space-between gl-p-0 gl-text-gray-900"
|
||||
>
|
||||
{{ item.text }}
|
||||
<gl-badge v-if="item.count" pill size="sm" variant="info">{{ item.count }}</gl-badge>
|
||||
<kbd v-else-if="item.shortcut" class="flat">?</kbd>
|
||||
</button>
|
||||
</template>
|
||||
</gl-disclosure-dropdown-group>
|
||||
</gl-disclosure-dropdown>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,29 @@
|
|||
background-color: $t-gray-a-08;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-with-notification {
|
||||
mix-blend-mode: unset !important; // Our tertiary buttons otherwise use another mix-blend mode, making border-color semi-transparent.
|
||||
|
||||
.notification {
|
||||
background-color: $blue-500;
|
||||
border: 2px solid $gray-10; // Same as the sidebar's background color.
|
||||
position: absolute;
|
||||
height: 9px;
|
||||
width: 9px;
|
||||
top: 5px;
|
||||
left: 22px;
|
||||
border-radius: 50%;
|
||||
transition: background-color 100ms linear, border-color 100ms linear;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.notification {
|
||||
border-color: $gray-50; // Same as the button's hover background color.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.with-performance-bar .super-sidebar {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
def index
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@mode = params[:state].presence || 'overview'
|
||||
@mode = fetch_mode
|
||||
next render_404 unless @mode
|
||||
|
||||
@sort = sort_param || default_sort
|
||||
@overview_max_branches = 5
|
||||
|
||||
|
|
@ -211,6 +213,14 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
@branches = @active_branches + @stale_branches
|
||||
end
|
||||
|
||||
def fetch_mode
|
||||
state = params[:state].presence
|
||||
|
||||
return 'overview' unless state
|
||||
|
||||
state.presence_in(%w[active stale all overview])
|
||||
end
|
||||
|
||||
def confidential_issue_project
|
||||
return if params[:confidential_issue_project_id].blank?
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ module SidebarsHelper
|
|||
create_new_menu_groups: create_new_menu_groups(group: group, project: project),
|
||||
merge_request_menu: create_merge_request_menu(user),
|
||||
support_path: support_url,
|
||||
display_whats_new: display_whats_new?
|
||||
display_whats_new: display_whats_new?,
|
||||
whats_new_most_recent_release_items_count: whats_new_most_recent_release_items_count,
|
||||
whats_new_version_digest: whats_new_version_digest
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,19 @@ foreign_key: :group_value_stream_id, inverse_of: :stages
|
|||
alias_attribute :value_stream_id, :group_value_stream_id
|
||||
|
||||
def self.distinct_stages_within_hierarchy(namespace)
|
||||
# Looking up the whole hierarchy including all kinds (type) of Namespace records.
|
||||
# We're doing a custom traversal_ids query because:
|
||||
# - The traversal_ids based `self_and_descendants` doesn't include the ProjectNamespace records.
|
||||
# - The default recursive lookup also excludes the ProjectNamespace records.
|
||||
#
|
||||
# Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/386124
|
||||
all_namespace_ids =
|
||||
Namespace
|
||||
.select(Arel.sql('namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)]').as('id'))
|
||||
.where("traversal_ids @> ('{?}')", namespace.id)
|
||||
|
||||
with_preloaded_labels
|
||||
.where(group_id: namespace.self_and_descendants.select(:id))
|
||||
.where(parent_id: all_namespace_ids)
|
||||
.select("DISTINCT ON(stage_event_hash_id) #{quoted_table_name}.*")
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class AuditEvent < ApplicationRecord
|
|||
|
||||
def lazy_author
|
||||
BatchLoader.for(author_id).batch do |author_ids, loader|
|
||||
User.select(:id, :name, :username).where(id: author_ids).find_each do |user|
|
||||
User.select(:id, :name, :username, :email).where(id: author_ids).find_each do |user|
|
||||
loader.call(user.id, user)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ module Integrations
|
|||
class BaseMessage
|
||||
RELATIVE_LINK_REGEX = %r{!\[[^\]]*\]\((/uploads/[^\)]*)\)}.freeze
|
||||
|
||||
# Markup characters which are used for links in HTML, Markdown,
|
||||
# and Slack "mrkdwn" syntax (`<http://example.com|Label>`).
|
||||
UNSAFE_MARKUP_CHARACTERS = '<>[]|'
|
||||
|
||||
attr_reader :markdown
|
||||
attr_reader :user_full_name
|
||||
attr_reader :user_name
|
||||
|
|
@ -85,7 +81,7 @@ module Integrations
|
|||
# - https://api.slack.com/reference/surfaces/formatting#escaping
|
||||
# - https://gitlab.com/gitlab-org/slack-notifier#escaping
|
||||
def strip_markup(string)
|
||||
string&.delete(UNSAFE_MARKUP_CHARACTERS)
|
||||
SlackMarkdownSanitizer.sanitize(string)
|
||||
end
|
||||
|
||||
def attachment_color
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- title: "Deprecate legacy Gitaly configuration methods" # The name of the feature to be deprecated
|
||||
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
|
||||
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
|
||||
removal_milestone: "16.0" # The milestone when this feature is planned to be removed
|
||||
breaking_change: true # If this deprecation is a breaking change, set this value to true
|
||||
reporter: mjwood # GitLab username of the person reporting the deprecation
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
# REQUIRED FIELDS
|
||||
#
|
||||
- title: "Support for Praefect custom metrics endpoint configuration"
|
||||
announcement_milestone: "15.9" # (required) The milestone when this feature was first announced as deprecated.
|
||||
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
|
||||
breaking_change: true # (required) Change to false if this is not a breaking change.
|
||||
reporter: mjwood # (required) GitLab username of the person reporting the change
|
||||
stage: Gitaly # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/390266 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
Support for using the `prometheus_exclude_database_from_default_metrics` configuration value is deprecated because using it is non-performant. Instead, all metrics
|
||||
that scrape the Praefect database will be exported to the `/db_metrics` endpoint. This may require updating your metrics collection targets.
|
||||
#
|
||||
# OPTIONAL END OF SUPPORT FIELDS
|
||||
#
|
||||
# If an End of Support period applies, the announcement should be shared with GitLab Support
|
||||
# in the `#spt_managers` channel in Slack, and mention `@gitlab-com/support` in this MR.
|
||||
#
|
||||
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
#
|
||||
# OTHER OPTIONAL FIELDS
|
||||
#
|
||||
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
documentation_url: # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
||||
|
|
@ -788,3 +788,22 @@ FATAL: invalid argument
|
|||
```
|
||||
|
||||
If a job artifact fails to upload with the above error when using consolidated object storage, make sure you are [using separate buckets](object_storage.md#use-separate-buckets) for each data type.
|
||||
|
||||
### Job artifacts fail to upload with `FATAL: invalid argument` when using Windows mount
|
||||
|
||||
If you are using a Windows mount with CIFS for job artifacts, you may see an
|
||||
`invalid argument` error when the runner attempts to upload artifacts:
|
||||
|
||||
```plaintext
|
||||
WARNING: Uploading artifacts as "dotenv" to coordinator... POST https://<your-gitlab-instance>/api/v4/jobs/<JOB_ID>/artifacts: 500 Internal Server Error id=1296 responseStatus=500 Internal Server Error status=500 token=*****
|
||||
FATAL: invalid argument
|
||||
```
|
||||
|
||||
To work around this issue, you can try:
|
||||
|
||||
- Switching to an ext4 mount instead of CIFS.
|
||||
- Upgrading to at least Linux kernel 5.15 which contains a number of important bug fixes
|
||||
relating to CIFS file leases.
|
||||
- For older kernels, using the `nolease` mount option to disable file leasing.
|
||||
|
||||
For more information, [see the investigation details](https://gitlab.com/gitlab-org/gitlab/-/issues/389995).
|
||||
|
|
|
|||
|
|
@ -96,6 +96,24 @@ def perform
|
|||
end
|
||||
```
|
||||
|
||||
## Failure handling
|
||||
|
||||
Failures are typically handled by Sidekiq itself, which takes advantage of the inbuilt retry mechanism mentioned above. You should allow exceptions to be raised so that Sidekiq can reschedule the job.
|
||||
|
||||
If you need to perform an action when a job fails after all of its retry attempts, add it to the `sidekiq_retries_exhausted` method.
|
||||
|
||||
```ruby
|
||||
sidekiq_retries_exhausted do |msg, ex|
|
||||
project = Project.find(msg['args'].first)
|
||||
project.perform_a_rollback # handle the permanent failure
|
||||
end
|
||||
|
||||
def perform(project_id)
|
||||
project = Project.find(project_id)
|
||||
project.some_action # throws an exception
|
||||
end
|
||||
```
|
||||
|
||||
## Sidekiq Queues
|
||||
|
||||
Previously, each worker had its own queue, which was automatically set based on the
|
||||
|
|
|
|||
|
|
@ -139,6 +139,21 @@ The option will no longer appear as a group setting. Self-managed users will sti
|
|||
|
||||
The option to delete projects immediately by default was deprecated to prevent users from accidentally taking this action and permanently losing projects.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
|
||||
### Support for Praefect custom metrics endpoint configuration
|
||||
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> <span class="removal-date"></span>
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
Review the details carefully before upgrading.
|
||||
|
||||
Support for using the `prometheus_exclude_database_from_default_metrics` configuration value is deprecated because using it is non-performant. Instead, all metrics
|
||||
that scrape the Praefect database will be exported to the `/db_metrics` endpoint. This may require updating your metrics collection targets.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1754,11 +1769,11 @@ The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 1
|
|||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-150 breaking-change">
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
|
||||
### Deprecate legacy Gitaly configuration methods
|
||||
|
||||
Planned removal: GitLab <span class="removal-milestone">15.0</span> <span class="removal-date"></span>
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> <span class="removal-date"></span>
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
|
|
|
|||
|
|
@ -274,3 +274,18 @@ Therefore, in projects with compliance frameworks, we recommend replacing
|
|||
pipeline feature.
|
||||
|
||||
This alternative ensures the compliance pipeline does not re-start the parent pipeline.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot remove compliance framework from a project
|
||||
|
||||
If you move a project, the compliance framework can become orphaned and can't be removed. To manually remove a compliance framework from a project, run the following GraphQL
|
||||
mutation with your project's ID:
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
projectSetComplianceFramework(input: {projectId: "gid://gitlab/Project/1234567", complianceFrameworkId: null}) {
|
||||
errors
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -262,6 +262,21 @@ To filter:
|
|||
1. From the dropdown list, select the scope or enter plain text to search by epic title or description.
|
||||
1. Press <kbd>Enter</kbd> on your keyboard. The list is filtered.
|
||||
|
||||
### Filter with the OR operator
|
||||
|
||||
> OR filtering for labels was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/382969) in GitLab 15.9 [with a flag](../../../administration/feature_flags.md) named `or_issuable_queries`. Disabled by default.
|
||||
|
||||
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 `or_issuable_queries`.
|
||||
The feature is not ready for production use.
|
||||
|
||||
When this feature is enabled, you can use the OR operator (**is one of: `||`**)
|
||||
to [filter the list of epics](#filter-the-list-of-epics) by labels.
|
||||
|
||||
`is one of` represents an inclusive OR. For example, if you filter by `Label is one of Deliverable` and
|
||||
`Label is one of UX`, GitLab shows epics with either `Deliverable`, `UX`, or both labels.
|
||||
|
||||
## Sort the list of epics
|
||||
|
||||
You can sort the epics list by:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SlackMarkdownSanitizer
|
||||
# Markup characters which are used for links in HTML, Markdown,
|
||||
# and Slack "mrkdwn" syntax (`<http://example.com|Label>`).
|
||||
UNSAFE_MARKUP_CHARACTERS = '<>[]|'
|
||||
|
||||
def self.sanitize(string)
|
||||
string&.delete(UNSAFE_MARKUP_CHARACTERS)
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'gitlab-qa', '~> 8', '>= 8.15.3', require: 'gitlab/qa'
|
||||
gem 'gitlab-qa', '~> 9', require: 'gitlab/qa'
|
||||
gem 'activesupport', '~> 6.1.7.2' # This should stay in sync with the root's Gemfile
|
||||
gem 'allure-rspec', '~> 2.20.0'
|
||||
gem 'capybara', '~> 3.38.0'
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ GEM
|
|||
gitlab (4.18.0)
|
||||
httparty (~> 0.18)
|
||||
terminal-table (>= 1.5.1)
|
||||
gitlab-qa (8.15.3)
|
||||
gitlab-qa (9.0.0)
|
||||
activesupport (~> 6.1)
|
||||
gitlab (~> 4.18.0)
|
||||
http (~> 5.0)
|
||||
|
|
@ -317,7 +317,7 @@ DEPENDENCIES
|
|||
faraday-retry (~> 2.0)
|
||||
fog-core (= 2.1.0)
|
||||
fog-google (~> 1.19)
|
||||
gitlab-qa (~> 8, >= 8.15.3)
|
||||
gitlab-qa (~> 9)
|
||||
influxdb-client (~> 2.9)
|
||||
knapsack (~> 4.0)
|
||||
nokogiri (~> 1.14, >= 1.14.1)
|
||||
|
|
|
|||
|
|
@ -676,6 +676,18 @@ RSpec.describe Projects::BranchesController do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when state is not supported' do
|
||||
before do
|
||||
get :index, format: :html, params: {
|
||||
namespace_id: project.namespace, project_id: project, state: 'unknown'
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns 404 page' do
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'sorting', :aggregate_failures do
|
||||
let(:sort) { 'name_asc' }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { GlDisclosureDropdown } from '@gitlab/ui';
|
||||
import { GlDisclosureDropdownGroup } from '@gitlab/ui';
|
||||
import { within } from '@testing-library/dom';
|
||||
import toggleWhatsNewDrawer from '~/whats_new';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import HelpCenter from '~/super_sidebar/components/help_center.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import { PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
|
||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||
import { STORAGE_KEY } from '~/whats_new/utils/notification';
|
||||
import { sidebarData } from '../mock_data';
|
||||
|
||||
jest.mock('~/whats_new');
|
||||
|
|
@ -12,11 +14,14 @@ jest.mock('~/whats_new');
|
|||
describe('HelpCenter component', () => {
|
||||
let wrapper;
|
||||
|
||||
const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
|
||||
const findDropdownGroup = (i = 0) => {
|
||||
return wrapper.findAllComponents(GlDisclosureDropdownGroup).at(i);
|
||||
};
|
||||
const withinComponent = () => within(wrapper.element);
|
||||
const findButton = (name) => withinComponent().getByRole('button', { name });
|
||||
|
||||
const createWrapper = () => {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const createWrapper = (sidebarData) => {
|
||||
wrapper = mountExtended(HelpCenter, {
|
||||
propsData: { sidebarData },
|
||||
});
|
||||
|
|
@ -24,11 +29,11 @@ describe('HelpCenter component', () => {
|
|||
|
||||
describe('default', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper();
|
||||
createWrapper(sidebarData);
|
||||
});
|
||||
|
||||
it('renders menu items', () => {
|
||||
expect(findDropdown().props('items')[0].items).toEqual([
|
||||
expect(findDropdownGroup(0).props('group').items).toEqual([
|
||||
{ text: HelpCenter.i18n.help, href: helpPagePath() },
|
||||
{ text: HelpCenter.i18n.support, href: sidebarData.support_path },
|
||||
{ text: HelpCenter.i18n.docs, href: 'https://docs.gitlab.com' },
|
||||
|
|
@ -41,7 +46,7 @@ describe('HelpCenter component', () => {
|
|||
{ text: HelpCenter.i18n.feedback, href: 'https://about.gitlab.com/submit-feedback' },
|
||||
]);
|
||||
|
||||
expect(findDropdown().props('items')[1].items).toEqual([
|
||||
expect(findDropdownGroup(1).props('group').items).toEqual([
|
||||
expect.objectContaining({ text: HelpCenter.i18n.shortcuts }),
|
||||
expect.objectContaining({ text: HelpCenter.i18n.whatsnew }),
|
||||
]);
|
||||
|
|
@ -51,7 +56,7 @@ describe('HelpCenter component', () => {
|
|||
beforeEach(() => {
|
||||
jest.spyOn(wrapper.vm.$refs.dropdown, 'close');
|
||||
window.toggleShortcutsHelp = jest.fn();
|
||||
findButton('Keyboard shortcuts').click();
|
||||
findButton('Keyboard shortcuts ?').click();
|
||||
});
|
||||
|
||||
it('closes the dropdown', () => {
|
||||
|
|
@ -66,7 +71,7 @@ describe('HelpCenter component', () => {
|
|||
describe('showWhatsNew', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(wrapper.vm.$refs.dropdown, 'close');
|
||||
findButton("What's new").click();
|
||||
findButton("What's new 5").click();
|
||||
});
|
||||
|
||||
it('closes the dropdown', () => {
|
||||
|
|
@ -83,5 +88,50 @@ describe('HelpCenter component', () => {
|
|||
expect(toggleWhatsNewDrawer).toHaveBeenLastCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldShowWhatsNewNotification', () => {
|
||||
describe('when setting is disabled', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ ...sidebarData, display_whats_new: false });
|
||||
});
|
||||
|
||||
it('is false', () => {
|
||||
expect(wrapper.vm.showWhatsNewNotification).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when setting is enabled', () => {
|
||||
useLocalStorageSpy();
|
||||
|
||||
beforeEach(() => {
|
||||
createWrapper({ ...sidebarData, display_whats_new: true });
|
||||
});
|
||||
|
||||
it('is true', () => {
|
||||
expect(wrapper.vm.showWhatsNewNotification).toBe(true);
|
||||
});
|
||||
|
||||
describe('when "What\'s new" drawer got opened', () => {
|
||||
beforeEach(() => {
|
||||
findButton("What's new 5").click();
|
||||
});
|
||||
|
||||
it('is false', () => {
|
||||
expect(wrapper.vm.showWhatsNewNotification).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with matching version digest in local storage', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.setItem(STORAGE_KEY, 1);
|
||||
createWrapper({ ...sidebarData, display_whats_new: true });
|
||||
});
|
||||
|
||||
it('is false', () => {
|
||||
expect(wrapper.vm.showWhatsNewNotification).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -69,4 +69,6 @@ export const sidebarData = {
|
|||
merge_request_menu: mergeRequestMenuGroup,
|
||||
support_path: '/support',
|
||||
display_whats_new: true,
|
||||
whats_new_most_recent_release_items_count: 5,
|
||||
whats_new_version_digest: 1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ RSpec.describe SidebarsHelper do
|
|||
issues_dashboard_path: issues_dashboard_path(assignee_username: user.username),
|
||||
total_merge_requests_count: 4,
|
||||
support_path: helper.support_url,
|
||||
display_whats_new: helper.display_whats_new?
|
||||
display_whats_new: helper.display_whats_new?,
|
||||
whats_new_most_recent_release_items_count: helper.whats_new_most_recent_release_items_count,
|
||||
whats_new_version_digest: helper.whats_new_version_digest
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe SlackMarkdownSanitizer, feature_category: :integrations do
|
||||
describe '.sanitize' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:input, :output) do
|
||||
nil | nil
|
||||
'' | ''
|
||||
'[label](url)' | 'label(url)'
|
||||
'<url|label>' | 'urllabel'
|
||||
'<a href="url">label</a>' | 'a href="url"label/a'
|
||||
end
|
||||
|
||||
with_them do
|
||||
it 'returns the expected output' do
|
||||
expect(described_class.sanitize(input)).to eq(output)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -27,6 +27,7 @@ RSpec.describe Analytics::CycleAnalytics::Stage, feature_category: :value_stream
|
|||
describe '.distinct_stages_within_hierarchy' do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:sub_group) { create(:group, parent: group) }
|
||||
let_it_be(:project) { create(:project, group: sub_group).reload }
|
||||
|
||||
before do
|
||||
# event identifiers are the same
|
||||
|
|
@ -36,12 +37,19 @@ RSpec.describe Analytics::CycleAnalytics::Stage, feature_category: :value_stream
|
|||
start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
|
||||
create(:cycle_analytics_stage, name: 'Stage A3', namespace: sub_group,
|
||||
start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
|
||||
create(:cycle_analytics_stage, name: 'Stage A4', project: project,
|
||||
start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
|
||||
|
||||
create(:cycle_analytics_stage,
|
||||
name: 'Stage B1',
|
||||
namespace: group,
|
||||
start_event_identifier: :merge_request_last_build_started,
|
||||
end_event_identifier: :merge_request_last_build_finished)
|
||||
|
||||
create(:cycle_analytics_stage, name: 'Stage C1', project: project,
|
||||
start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production)
|
||||
create(:cycle_analytics_stage, name: 'Stage C2', project: project,
|
||||
start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production)
|
||||
end
|
||||
|
||||
it 'returns distinct stages by the event identifiers' do
|
||||
|
|
@ -49,12 +57,13 @@ RSpec.describe Analytics::CycleAnalytics::Stage, feature_category: :value_stream
|
|||
|
||||
expected_event_pairs = [
|
||||
%w[merge_request_created merge_request_merged],
|
||||
%w[merge_request_last_build_started merge_request_last_build_finished]
|
||||
]
|
||||
%w[merge_request_last_build_started merge_request_last_build_finished],
|
||||
%w[issue_created issue_deployed_to_production]
|
||||
].sort
|
||||
|
||||
current_event_pairs = stages.map do |stage|
|
||||
[stage.start_event_identifier, stage.end_event_identifier]
|
||||
end
|
||||
end.sort
|
||||
|
||||
expect(current_event_pairs).to eq(expected_event_pairs)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -42,6 +42,26 @@ RSpec.shared_examples 'issue boards sidebar' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'editing issue title' do
|
||||
it 'edits issue title' do
|
||||
page.within('[data-testid="sidebar-title"]') do
|
||||
click_button 'Edit'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
find('input').set('Test title')
|
||||
|
||||
click_button 'Save changes'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
expect(page).to have_content('Test title')
|
||||
end
|
||||
|
||||
expect(first_card).to have_content('Test title')
|
||||
end
|
||||
end
|
||||
|
||||
context 'editing issue milestone', :js do
|
||||
it_behaves_like 'milestone sidebar widget'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ require (
|
|||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/smartystreets/goconvey v1.7.2
|
||||
github.com/stretchr/testify v1.8.1
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.0
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.1
|
||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
|
||||
gitlab.com/gitlab-org/labkit v1.17.0
|
||||
gocloud.dev v0.28.0
|
||||
|
|
|
|||
|
|
@ -1842,8 +1842,8 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX
|
|||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.0 h1:v72gyGuzM2XTLWodIfOBDEzCj9bRt8wiQVT2RIQ37F8=
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.0/go.mod h1:typ7BQ9JuglkeTvW3Vn1SwFcZ1FMn8P3GrWcPuZQ0EU=
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.1 h1:i/38/jLhvXwiztdrUCh9YxCrYufWS0K6pKQnbF3vy8U=
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.8.1/go.mod h1:typ7BQ9JuglkeTvW3Vn1SwFcZ1FMn8P3GrWcPuZQ0EU=
|
||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
|
||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE=
|
||||
gitlab.com/gitlab-org/labkit v1.17.0 h1:mEkoLzXorLNdt8NkfgYS5xMDhdqCsIJaeEVtSf7d8cU=
|
||||
|
|
|
|||
Loading…
Reference in New Issue