Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4b4c254b2c
commit
8e1bb8745b
|
@ -64,6 +64,7 @@ variables:
|
|||
NODE_ENV: "test"
|
||||
BUNDLE_WITHOUT: "production:development"
|
||||
BUNDLE_INSTALL_FLAGS: "--jobs=$(nproc) --retry=3 --quiet"
|
||||
BUNDLE_FROZEN: "true"
|
||||
# we override the max_old_space_size to prevent OOM errors
|
||||
NODE_OPTIONS: --max_old_space_size=3584
|
||||
GIT_DEPTH: "20"
|
||||
|
|
|
@ -177,6 +177,8 @@ Dangerfile @gl-quality/eng-prod
|
|||
|
||||
[Application Security]
|
||||
/app/assets/javascripts/lib/dompurify.js @gitlab-com/gl-security/appsec
|
||||
/app/assets/javascripts/gfm_auto_complete.js @gitlab-com/gl-security/appsec
|
||||
/ee/app/assets/javascripts/gfm_auto_complete.js @gitlab-com/gl-security/appsec
|
||||
/app/validators/addressable_url_validator.rb @gitlab-com/gl-security/appsec
|
||||
/app/validators/public_url_validator.rb @gitlab-com/gl-security/appsec
|
||||
/config/initializers/content_security_policy.rb @gitlab-com/gl-security/appsec
|
||||
|
|
|
@ -72,5 +72,6 @@ danger-review-local:
|
|||
reviewers-recommender:
|
||||
extends:
|
||||
- .default-retry
|
||||
- .review:rules:reviewers-recommender
|
||||
stage: test
|
||||
needs: []
|
||||
|
|
|
@ -1663,6 +1663,12 @@
|
|||
- <<: *if-merge-request
|
||||
changes: *danger-patterns
|
||||
|
||||
.review:rules:reviewers-recommender:
|
||||
rules:
|
||||
- <<: *if-not-canonical-namespace
|
||||
when: never
|
||||
- <<: *if-merge-request
|
||||
|
||||
###############
|
||||
# Setup rules #
|
||||
###############
|
||||
|
|
|
@ -171,7 +171,6 @@ add-jh-folder:
|
|||
- curl --location -o "jh-folder.tar.gz" "https://gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab/-/archive/${JH_BRANCH}/gitlab-${JH_BRANCH}.tar.gz?path=jh"
|
||||
- tar -xf "jh-folder.tar.gz"
|
||||
- mv "gitlab-${JH_BRANCH}-jh/jh/" ./
|
||||
- cp Gemfile.lock jh/
|
||||
- ls -l jh/
|
||||
artifacts:
|
||||
expire_in: 2d
|
||||
|
|
|
@ -1 +1 @@
|
|||
803b179a6834fbebcc7886083731bb0f4a67c796
|
||||
b2c8eaa672c9f2dc4b55477a3876f957e2c9a768
|
||||
|
|
|
@ -354,7 +354,7 @@ export default {
|
|||
>
|
||||
<header
|
||||
v-if="showToolbar"
|
||||
class="row-content-block gl-border-t-0 gl-py-3 gl-display-flex"
|
||||
class="gl-display-flex gl-my-0 gl-text-gray-900"
|
||||
data-testid="design-toolbar-wrapper"
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -32,9 +32,12 @@ export default {
|
|||
...mapState('pipelines', ['latestPipeline']),
|
||||
},
|
||||
watch: {
|
||||
lastCommit() {
|
||||
lastCommit: {
|
||||
handler() {
|
||||
this.initPipelinePolling();
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.startTimer();
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
<script>
|
||||
import { GlButton, GlCard } from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
GlCard,
|
||||
},
|
||||
props: {
|
||||
upgradePlanPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
showPremiumMessage: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
showUltimateMessage: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.showUltimateMessage
|
||||
? this.$options.i18n.titleUltimate
|
||||
: this.$options.i18n.titlePremium;
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
titleUltimate: s__('JiraService|This is an Ultimate feature'),
|
||||
titlePremium: s__('JiraService|This is a Premium feature'),
|
||||
content: s__('JiraService|Upgrade your plan to enable this feature of the Jira Integration.'),
|
||||
upgrade: __('Upgrade your plan'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-card>
|
||||
<strong>{{ title }}</strong>
|
||||
<p>{{ $options.i18n.content }}</p>
|
||||
<gl-button v-if="upgradePlanPath" category="primary" variant="info" :href="upgradePlanPath">
|
||||
{{ $options.i18n.upgrade }}
|
||||
</gl-button>
|
||||
</gl-card>
|
||||
</template>
|
|
@ -21,7 +21,6 @@ function parseDatasetToProps(data) {
|
|||
type,
|
||||
commentDetail,
|
||||
projectKey,
|
||||
upgradePlanPath,
|
||||
learnMorePath,
|
||||
aboutPricingUrl,
|
||||
triggerEvents,
|
||||
|
@ -80,7 +79,6 @@ function parseDatasetToProps(data) {
|
|||
initialEnableJiraVulnerabilities: enableJiraVulnerabilities,
|
||||
initialVulnerabilitiesIssuetype: vulnerabilitiesIssuetype,
|
||||
initialProjectKey: projectKey,
|
||||
upgradePlanPath,
|
||||
},
|
||||
learnMorePath,
|
||||
aboutPricingUrl,
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import eventHub from '../event_hub';
|
||||
import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '../constants';
|
||||
import {
|
||||
TRIGGER_ELEMENT_BUTTON,
|
||||
TRIGGER_ELEMENT_SIDE_NAV,
|
||||
TRIGGER_DEFAULT_QA_SELECTOR,
|
||||
} from '../constants';
|
||||
|
||||
export default {
|
||||
components: { GlButton, GlLink, GlIcon },
|
||||
|
@ -46,12 +50,17 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
qaSelector: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: TRIGGER_DEFAULT_QA_SELECTOR,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
componentAttributes() {
|
||||
const baseAttributes = {
|
||||
class: this.classes,
|
||||
'data-qa-selector': 'invite_members_button',
|
||||
'data-qa-selector': this.qaSelector,
|
||||
'data-test-id': 'invite-members-button',
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ export const USERS_FILTER_ALL = 'all';
|
|||
export const USERS_FILTER_SAML_PROVIDER_ID = 'saml_provider_id';
|
||||
export const TRIGGER_ELEMENT_BUTTON = 'button';
|
||||
export const TRIGGER_ELEMENT_SIDE_NAV = 'side-nav';
|
||||
export const TRIGGER_DEFAULT_QA_SELECTOR = 'invite_members_button';
|
||||
export const MEMBERS_MODAL_DEFAULT_TITLE = s__('InviteMembersModal|Invite members');
|
||||
export const MEMBERS_MODAL_CELEBRATE_TITLE = s__(
|
||||
'InviteMembersModal|GitLab is better with colleagues!',
|
||||
|
|
|
@ -11,6 +11,7 @@ import createFlash from '~/flash';
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
import api from '~/api';
|
||||
|
||||
// Todo: Remove this when fixing issue in input_setter plugin
|
||||
const InputSetter = { ...ISetter };
|
||||
|
@ -149,7 +150,7 @@ export default class CreateMergeRequestDropdown {
|
|||
});
|
||||
}
|
||||
|
||||
createBranch() {
|
||||
createBranch(navigateToBranch = true) {
|
||||
this.isCreatingBranch = true;
|
||||
|
||||
return axios
|
||||
|
@ -158,7 +159,10 @@ export default class CreateMergeRequestDropdown {
|
|||
})
|
||||
.then(({ data }) => {
|
||||
this.branchCreated = true;
|
||||
|
||||
if (navigateToBranch) {
|
||||
window.location.href = data.url;
|
||||
}
|
||||
})
|
||||
.catch(() =>
|
||||
createFlash({
|
||||
|
@ -170,7 +174,9 @@ export default class CreateMergeRequestDropdown {
|
|||
createMergeRequest() {
|
||||
return new Promise(() => {
|
||||
this.isCreatingMergeRequest = true;
|
||||
return this.createBranch().then(() => {
|
||||
return this.createBranch(false)
|
||||
.then(() => api.trackRedisHllUserEvent('i_code_review_user_create_mr_from_issue'))
|
||||
.then(() => {
|
||||
let path = canCreateConfidentialMergeRequest()
|
||||
? this.createMrPath.replace(
|
||||
this.projectPath,
|
||||
|
|
|
@ -42,10 +42,6 @@ body {
|
|||
text-align: left;
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -105,15 +101,6 @@ button::-moz-focus-inner,
|
|||
[type="search"] {
|
||||
outline-offset: -2px;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 0.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #fafafa;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.1875rem;
|
||||
}
|
||||
.list-unstyled {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
|
@ -547,10 +534,6 @@ html [type="button"],
|
|||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -27,10 +27,6 @@ body {
|
|||
text-align: left;
|
||||
background-color: #fff;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -90,15 +86,6 @@ button::-moz-focus-inner,
|
|||
[type="search"] {
|
||||
outline-offset: -2px;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 0.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #303030;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.1875rem;
|
||||
}
|
||||
.list-unstyled {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
|
@ -532,10 +519,6 @@ html [type="button"],
|
|||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ module MergeRequestsHelper
|
|||
end
|
||||
|
||||
def toggle_draft_merge_request_path(issuable)
|
||||
wip_event = issuable.work_in_progress? ? 'unwip' : 'wip'
|
||||
wip_event = issuable.draft? ? 'unwip' : 'wip'
|
||||
|
||||
issuable_path(issuable, { merge_request: { wip_event: wip_event } })
|
||||
end
|
||||
|
|
|
@ -519,9 +519,10 @@ class Commit
|
|||
#
|
||||
DRAFT_REGEX = /\A\s*#{Gitlab::Regex.merge_request_draft}|(fixup!|squash!)\s/.freeze
|
||||
|
||||
def work_in_progress?
|
||||
def draft?
|
||||
!!(title =~ DRAFT_REGEX)
|
||||
end
|
||||
alias_method :work_in_progress?, :draft?
|
||||
|
||||
def merged_merge_request?(user)
|
||||
!!merged_merge_request(user)
|
||||
|
|
|
@ -18,7 +18,8 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
|
|||
expose :rebase_in_progress?, as: :rebase_in_progress
|
||||
expose :commits_count
|
||||
expose :merge_ongoing?, as: :merge_ongoing
|
||||
expose :work_in_progress?, as: :work_in_progress
|
||||
expose :draft?, as: :draft
|
||||
expose :draft?, as: :work_in_progress
|
||||
expose :cannot_be_merged?, as: :has_conflicts
|
||||
expose :can_be_merged?, as: :can_be_merged
|
||||
expose :remove_source_branch?, as: :remove_source_branch
|
||||
|
|
|
@ -54,7 +54,7 @@ module Issuable
|
|||
def create_draft_note(old_title)
|
||||
return unless issuable.is_a?(MergeRequest)
|
||||
|
||||
if MergeRequest.work_in_progress?(old_title) != issuable.work_in_progress?
|
||||
if MergeRequest.draft?(old_title) != issuable.draft?
|
||||
SystemNoteService.handle_merge_request_draft(issuable, issuable.project, current_user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -255,17 +255,17 @@ module MergeRequests
|
|||
|
||||
commit_shas = merge_request.commit_shas
|
||||
|
||||
wip_commit = @commits.detect do |commit|
|
||||
commit.work_in_progress? && commit_shas.include?(commit.sha)
|
||||
draft_commit = @commits.detect do |commit|
|
||||
commit.draft? && commit_shas.include?(commit.sha)
|
||||
end
|
||||
|
||||
if wip_commit && !merge_request.work_in_progress?
|
||||
merge_request.update(title: merge_request.wip_title)
|
||||
if draft_commit && !merge_request.draft?
|
||||
merge_request.update(title: merge_request.draft_title)
|
||||
SystemNoteService.add_merge_request_draft_from_commit(
|
||||
merge_request,
|
||||
merge_request.project,
|
||||
@current_user,
|
||||
wip_commit
|
||||
draft_commit
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -180,16 +180,16 @@ module MergeRequests
|
|||
return unless changed_fields.include?("title")
|
||||
|
||||
old_title, new_title = merge_request.previous_changes["title"]
|
||||
old_title_wip = MergeRequest.work_in_progress?(old_title)
|
||||
new_title_wip = MergeRequest.work_in_progress?(new_title)
|
||||
old_title_draft = MergeRequest.draft?(old_title)
|
||||
new_title_draft = MergeRequest.draft?(new_title)
|
||||
|
||||
if !old_title_wip && new_title_wip
|
||||
# Marked as Draft/WIP
|
||||
if !old_title_draft && new_title_draft
|
||||
# Marked as Draft
|
||||
#
|
||||
merge_request_activity_counter
|
||||
.track_marked_as_draft_action(user: current_user)
|
||||
elsif old_title_wip && !new_title_wip
|
||||
# Unmarked as Draft/WIP
|
||||
elsif old_title_draft && !new_title_draft
|
||||
# Unmarked as Draft
|
||||
#
|
||||
notify_draft_status_changed(merge_request)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ module SystemNotes
|
|||
end
|
||||
|
||||
def handle_merge_request_draft
|
||||
action = noteable.work_in_progress? ? "draft" : "ready"
|
||||
action = noteable.draft? ? "draft" : "ready"
|
||||
|
||||
body = "marked this merge request as **#{action}**"
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
.js-invite-members-trigger{ data: { trigger_source: 'group-side-nav',
|
||||
icon: 'users',
|
||||
display_text: title,
|
||||
trigger_element: 'side-nav'} }
|
||||
trigger_element: 'side-nav',
|
||||
qa_selector: 'invite_members_sidebar_button' } }
|
||||
|
||||
= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
|
||||
= render 'groups/invite_members_modal', group: group
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.container-fluid
|
||||
.header-content.js-header-content
|
||||
.title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0
|
||||
%h1.title
|
||||
.title
|
||||
%span.gl-sr-only GitLab
|
||||
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
|
||||
= brand_header_logo
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
.js-invite-members-trigger{ data: { trigger_source: 'project-side-nav',
|
||||
icon: 'users',
|
||||
display_text: title,
|
||||
trigger_element: 'side-nav'} }
|
||||
trigger_element: 'side-nav',
|
||||
qa_selector: 'invite_members_sidebar_button' } }
|
||||
|
||||
= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
|
||||
= render 'projects/invite_members_modal', project: project
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
%li.gl-new-dropdown-item
|
||||
= link_to toggle_draft_merge_request_path(@merge_request), method: :put, class: 'dropdown-item js-draft-toggle-button' do
|
||||
.gl-new-dropdown-item-text-wrapper
|
||||
= @merge_request.work_in_progress? ? _('Mark as ready') : _('Mark as draft')
|
||||
= @merge_request.draft? ? _('Mark as ready') : _('Mark as draft')
|
||||
%li.gl-new-dropdown-item.js-close-item
|
||||
= link_to close_issuable_path(@merge_request), method: :put, class: 'dropdown-item' do
|
||||
.gl-new-dropdown-item-text-wrapper
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
= _('Title')
|
||||
%i{ aria: { hidden: true } }= '*'
|
||||
|
||||
= render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?)
|
||||
= render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:draft?)
|
||||
#js-suggestions{ data: { project_path: @project.full_path } }
|
||||
|
||||
= render 'shared/issuable/form/type_selector', issuable: issuable, form: form
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
= form.text_field :title, required: true, aria: { required: true }, maxlength: 255, autofocus: true,
|
||||
autocomplete: 'off', class: 'form-control pad qa-issuable-form-title', placeholder: _('Title'), dir: 'auto'
|
||||
|
||||
- if issuable.respond_to?(:work_in_progress?)
|
||||
- if issuable.respond_to?(:draft?)
|
||||
.form-text.text-muted
|
||||
.js-wip-explanation{ style: "display: none;" }
|
||||
= remove_wip_text
|
||||
|
|
|
@ -2749,15 +2749,6 @@
|
|||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: project_daily_statistics
|
||||
:worker_name: ProjectDailyStatisticsWorker
|
||||
:feature_category: :source_code_management
|
||||
:has_external_dependencies:
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent:
|
||||
:tags: []
|
||||
- :name: project_destroy
|
||||
:worker_name: ProjectDestroyWorker
|
||||
:feature_category: :source_code_management
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/214585
|
||||
class ProjectDailyStatisticsWorker # rubocop:disable Scalability/IdempotentWorker
|
||||
include ApplicationWorker
|
||||
|
||||
data_consistency :always
|
||||
|
||||
sidekiq_options retry: 3
|
||||
|
||||
feature_category :source_code_management
|
||||
|
||||
def perform(project_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
|
||||
return unless project&.repository&.exists?
|
||||
|
||||
Projects::FetchStatisticsIncrementService.new(project).execute
|
||||
end
|
||||
end
|
|
@ -345,8 +345,6 @@
|
|||
- 3
|
||||
- - project_cache
|
||||
- 1
|
||||
- - project_daily_statistics
|
||||
- 1
|
||||
- - project_destroy
|
||||
- 1
|
||||
- - project_export
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropIndexNamespacesOnName < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_namespaces_on_name'
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name :namespaces, INDEX_NAME, if_exists: true
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
4d44b5cd1bcd731e841849c65f64a19960fa13cd90d1bda023e797db20b8b8c6
|
|
@ -20,6 +20,8 @@ are stored securely outside of your project's repository, and are not version co
|
|||
It is safe to store sensitive information in these files. Secure files support both
|
||||
plain text and binary file types.
|
||||
|
||||
You can manage secure files in the project settings, or with the [secure files API](../../api/secure_files.md).
|
||||
|
||||
Secure files can be [downloaded and used by CI/CD jobs](#use-secure-files-in-cicd-jobs)
|
||||
by using the [load-secure-files](https://gitlab.com/gitlab-org/incubation-engineering/devops-for-mobile-apps/load-secure-files)
|
||||
tool.
|
||||
|
@ -30,49 +32,14 @@ Additional features and capabilities are planned.
|
|||
|
||||
## Add a secure file to a project
|
||||
|
||||
To add a secure file to a project, use the [Secure Files API](../../api/secure_files.md#create-secure-file).
|
||||
To add a secure file to a project:
|
||||
|
||||
Send a POST request to the secure files endpoint for your project:
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/projects/:project_id/secure_files" --form "name=myfile.jks" --form "file=@/path/to/file/myfile.jks"
|
||||
```
|
||||
|
||||
The response returns all of the metadata for the file you just uploaded. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "myfile.jks",
|
||||
"checksum": "16630b189ab34b2e3504f4758e1054d2e478deda510b2b08cc0ef38d12e80aac",
|
||||
"checksum_algorithm": "sha256",
|
||||
"created_at": "2022-02-22T22:22:22.222Z"
|
||||
}
|
||||
```
|
||||
|
||||
## List all secure files in a project
|
||||
|
||||
To list all secure files in a project, use the [Secure Files API](../../api/secure_files.md#list-project-secure-files).
|
||||
|
||||
Send a GET request to the secure files endpoint for your project:
|
||||
|
||||
```shell
|
||||
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
"https://gitlab.example.com/api/v4/projects/:project_id/secure_files"
|
||||
```
|
||||
|
||||
The response returns an array of all of the secure files in the project. For example:
|
||||
|
||||
```json
|
||||
[{
|
||||
"id": 1,
|
||||
"name": "myfile.jks",
|
||||
"checksum": "16630b189ab34b2e3504f4758e1054d2e478deda510b2b08cc0ef38d12e80aac",
|
||||
"checksum_algorithm": "sha256",
|
||||
"created_at": "2022-02-22T22:22:22.222Z"
|
||||
}]
|
||||
```
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. In the **Secure Files** section, select **Manage**.
|
||||
1. Select **Upload File**.
|
||||
1. Find the file to upload, select **Open**, and the file upload begins immediately.
|
||||
The file shows up in the list when the upload is complete.
|
||||
|
||||
## Use secure files in CI/CD jobs
|
||||
|
||||
|
|
|
@ -213,32 +213,42 @@ HTML which differs from the canonical HTML examples from the specification.
|
|||
For every Markdown example in the GLFM specification, three
|
||||
versions of HTML can potentially be rendered from the example:
|
||||
|
||||
1. **Static HTML**: HTML produced by the backend (Ruby) renderer, which
|
||||
- Static HTML.
|
||||
- WYSIWYG HTML.
|
||||
- Canonical HTML.
|
||||
|
||||
#### Static HTML
|
||||
|
||||
**Static HTML** is HTML produced by the backend (Ruby) renderer, which
|
||||
contains extra styling and behavioral HTML. For example, **Create task** buttons
|
||||
added for dynamically creating an issue from a task list item.
|
||||
The GitLab [Markdown API](../../../api/markdown.md) generates HTML
|
||||
for a given Markdown string using this method.
|
||||
1. **WYSIWYG HTML**: HTML produced by the frontend (JavaScript) Content Editor,
|
||||
which includes parsing and rendering logic. Used to present an editable document
|
||||
|
||||
#### WYSIWYG HTML
|
||||
|
||||
**WYSIWYG HTML** is HTML produced by the frontend (JavaScript) Content Editor,
|
||||
which includes parsing and rendering logic. It is used to present an editable document
|
||||
in the ProseMirror WYSIWYG editor.
|
||||
1. **Canonical HTML**: The clean, basic version of HTML rendered from Markdown.
|
||||
|
||||
#### Canonical HTML
|
||||
|
||||
**Canonical HTML** is the clean, basic version of HTML rendered from Markdown.
|
||||
|
||||
1. For the examples which come from the CommonMark specification and
|
||||
GFM extensions specification,
|
||||
the canonical HTML is the exact identical HTML found in the
|
||||
GFM
|
||||
`spec.txt` example blocks.
|
||||
GFM extensions specification, the canonical HTML is the exact identical HTML found in the
|
||||
GFM `spec.txt` example blocks.
|
||||
1. For GLFM extensions to the <abbr title="GitHub Flavored Markdown">GFM</abbr> / CommonMark
|
||||
specification, a `glfm_canonical_examples.txt`
|
||||
[input specification file](#input-specification-files) contains the
|
||||
Markdown examples and corresponding canonical HTML examples.
|
||||
specification, a `glfm_canonical_examples.txt` [input specification file](#input-specification-files)
|
||||
contains the Markdown examples and corresponding canonical HTML examples.
|
||||
|
||||
As the rendered static and WYSIWYG HTML from the backend (Ruby) and frontend (JavaScript)
|
||||
renderers contain extra HTML, their rendered HTML can be converted to canonical HTML
|
||||
by a [canonicalization](#canonicalization-of-html) process.
|
||||
### Canonicalization of HTML
|
||||
|
||||
#### Canonicalization of HTML
|
||||
The rendered [static HTML](#static-html) and [WYSIWYG HTML](#wysiwyg-html)
|
||||
from the backend (Ruby) and frontend (JavaScript) renderers usually contains extra styling
|
||||
or HTML elements, to support specific appearance and behavioral requirements.
|
||||
|
||||
Neither the backend (Ruby) nor the frontend (JavaScript) rendered can directly render canonical HTML.
|
||||
Neither the backend nor the frontend rendering logic can directly render the clean, basic canonical HTML.
|
||||
Nor should they be able to, because:
|
||||
|
||||
- It's not a direct requirement to support any GitLab application feature.
|
||||
|
@ -578,23 +588,57 @@ The actual file should not have these prefixed `|` characters.
|
|||
controls the behavior of the [scripts](#scripts) and [tests](#types-of-markdown-tests-driven-by-the-glfm-specification).
|
||||
|
||||
- It is manually updated.
|
||||
- It controls the status of automatic generation of files based on Markdown examples.
|
||||
- It allows example snapshot generation, Markdown conformance tests, or
|
||||
Markdown snapshot tests to be skipped for individual examples. For example, if
|
||||
they are unimplemented, broken, or cannot be tested for some reason.
|
||||
- The `skip_update_example_snapshot*` fields control the status of automatic generation of
|
||||
snapshot example entries based on Markdown examples.
|
||||
- The `skip_running_*` control allow Markdown conformance tests or
|
||||
Markdown snapshot tests to be skipped for individual examples.
|
||||
- This allows control over skipping this processing or testing of various examples when they
|
||||
are unimplemented, partially implemented, broken, or cannot be generated or tested for some reason.
|
||||
- All entries default to false. They can be set to true by specifying a Ruby
|
||||
value which evaluates as truthy. This could be the boolean `true` value, but ideally should
|
||||
be a string describing why the example's updating or testing is being skipped.
|
||||
- When a `skip_update_example_snapshot*` entry is true, the existing value is preserved.
|
||||
However, since the YAML is re-written, the style of the string value and its
|
||||
[Block Chomping Indicator (`|`)](https://yaml.org/spec/1.2.2/#8112-block-chomping-indicator)
|
||||
may be modified, because the Ruby `psych` YAML library automatically determines this.
|
||||
|
||||
The following optional entries are supported for each example. They all default to `false`:
|
||||
|
||||
- `skip_update_example_snapshots`: When true, skips any addition or update of any this example's entries
|
||||
in the [`spec/fixtures/glfm/example_snapshots/html.yml`](#specfixturesglfmexample_snapshotshtmlyml) file
|
||||
or the [`spec/fixtures/glfm/example_snapshots/prosemirror_json.yml`](#specfixturesglfmexample_snapshotsprosemirror_jsonyml) file.
|
||||
If this value is truthy, then no other `skip_update_example_snapshot_*` entries can be truthy,
|
||||
and an error is raised if any of them are.
|
||||
- `skip_update_example_snapshot_html_static`: When true, skips addition or update of this example's [static HTML](#static-html)
|
||||
entry in the [`spec/fixtures/glfm/example_snapshots/html.yml`](#specfixturesglfmexample_snapshotshtmlyml) file.
|
||||
- `skip_update_example_snapshot_html_wysiwyg`: When true, skips addition or update of this example's [WYSIWYG HTML](#wysiwyg-html)
|
||||
entry in the [`spec/fixtures/glfm/example_snapshots/html.yml`](#specfixturesglfmexample_snapshotshtmlyml) file.
|
||||
- `skip_update_example_snapshot_prosemirror_json`: When true, skips addition or update of this example's
|
||||
entry in the [`spec/fixtures/glfm/example_snapshots/prosemirror_json.yml`](#specfixturesglfmexample_snapshotsprosemirror_jsonyml) file.
|
||||
- `skip_running_conformance_static_tests`: When true, skips running the [Markdown conformance tests](#markdown-conformance-testing)
|
||||
of the [static HTML](#static-html) for this example.
|
||||
- `skip_running_conformance_wysiwyg_tests`: When true, skips running the [Markdown conformance tests](#markdown-conformance-testing)
|
||||
of the [WYSIWYG HTML](#wysiwyg-html) for this example.
|
||||
- `skip_running_snapshot_static_html_tests`: When true, skips running the [Markdown snapshot tests](#markdown-snapshot-testing)
|
||||
of the [static HTML](#multiple-versions-of-rendered-html) for this example.
|
||||
- `skip_running_snapshot_wysiwyg_html_tests`: When true, skips running the [Markdown snapshot tests](#markdown-snapshot-testing)
|
||||
of the [WYSIWYG HTML](#wysiwyg-html) for this example.
|
||||
- `skip_running_snapshot_prosemirror_json_tests`: When true, skips running the [Markdown snapshot tests](#markdown-snapshot-testing)
|
||||
of the [ProseMirror JSON](#specfixturesglfmexample_snapshotsprosemirror_jsonyml) for this example.
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml` sample entry:
|
||||
|
||||
```yaml
|
||||
07_99_an_example_with_incomplete_wysiwyg_implementation_1:
|
||||
skip_update_example_snapshots: false
|
||||
skip_update_example_snapshot_html_static: false
|
||||
skip_update_example_snapshot_html_wysiwyg: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_update_example_snapshots: 'An explanation of the reason for skipping.'
|
||||
skip_update_example_snapshot_html_static: 'An explanation of the reason for skipping.'
|
||||
skip_update_example_snapshot_html_wysiwyg: 'An explanation of the reason for skipping.'
|
||||
skip_update_example_snapshot_prosemirror_json: 'An explanation of the reason for skipping.'
|
||||
skip_running_conformance_static_tests: 'An explanation of the reason for skipping.'
|
||||
skip_running_conformance_wysiwyg_tests: 'An explanation of the reason for skipping.'
|
||||
skip_running_snapshot_static_html_tests: 'An explanation of the reason for skipping.'
|
||||
skip_running_snapshot_wysiwyg_html_tests: 'An explanation of the reason for skipping.'
|
||||
skip_running_snapshot_prosemirror_json_tests: 'An explanation of the reason for skipping.'
|
||||
```
|
||||
|
||||
#### Output specification files
|
||||
|
|
|
@ -22,9 +22,17 @@ it should be restricted on namespace scope.
|
|||
1. Check using:
|
||||
|
||||
```ruby
|
||||
project.feature_available?(:feature_symbol)
|
||||
project.licensed_feature_available?(:feature_symbol)
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```ruby
|
||||
group.licensed_feature_available?(:feature_symbol)
|
||||
```
|
||||
|
||||
For projects, `licensed_feature_available` delegates to its associated `namespace`.
|
||||
|
||||
## Restricting global features (instance)
|
||||
|
||||
However, for features such as [Geo](../administration/geo/index.md) and
|
||||
|
|
|
@ -52,9 +52,9 @@ work it needs to perform and how long it takes to complete:
|
|||
- Clean-ups, like removing unused columns.
|
||||
- Adding non-critical indices on high-traffic tables.
|
||||
- Adding non-critical indices that take a long time to create.
|
||||
1. [**Background migrations.**](database/background_migrations.md) These aren't regular Rails migrations, but application code that is
|
||||
1. [**Batched background migrations.**](database/batched_background_migrations.md) These aren't regular Rails migrations, but application code that is
|
||||
executed via Sidekiq jobs, although a post-deployment migration is used to schedule them. Use them only for data migrations that
|
||||
exceed the timing guidelines for post-deploy migrations. Background migrations should _not_ change the schema.
|
||||
exceed the timing guidelines for post-deploy migrations. Batched background migrations should _not_ change the schema.
|
||||
|
||||
Use the following diagram to guide your decision, but keep in mind that it is just a tool, and
|
||||
the final outcome will always be dependent on the specific changes being made:
|
||||
|
|
|
@ -329,7 +329,7 @@ The following table describes the rate limits for GitLab.com, both before and
|
|||
after the limits change in January, 2021:
|
||||
|
||||
| Rate limit | From 2021-02-12 | From 2022-02-03 |
|
||||
|:--------------------------------------------------------------------------|:------------------------------|:----------------------------------------|
|
||||
|:---------------------------------------------------------------------------|:------------------------------|:----------------------------------------|
|
||||
| **Protected paths** (for a given **IP address**) | **10** requests per minute | **10** requests per minute |
|
||||
| **Raw endpoint** traffic (for a given **project, commit, and file path**) | **300** requests per minute | **300** requests per minute |
|
||||
| **Unauthenticated** traffic (from a given **IP address**) | **500** requests per minute | **500** requests per minute |
|
||||
|
@ -341,6 +341,7 @@ after the limits change in January, 2021:
|
|||
| **Advanced, project, and group search** API (for a given **IP address**) | **10** requests per minute | **10** requests per minute |
|
||||
| **GitLab Pages** requests (for a given **IP address**) | | **1000** requests per **50 seconds** |
|
||||
| **GitLab Pages** requests (for a given **GitLab Pages domain**) | | **5000** requests per **10 seconds** |
|
||||
| **Pipeline creation** requests (for a given **project, user, and commit**) | | **25** requests per minute |
|
||||
|
||||
More details are available on the rate limits for [protected
|
||||
paths](#protected-paths-throttle) and [raw
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
---
|
||||
- 06_05__inlines__emphasis_and_strong_emphasis__37:
|
||||
skip_update_example_snapshots: 'Psych YAML library has a problem with dumping "5__6__78", it thinks its an invalid integer'
|
||||
- 07_01_first_gitlab_specific_section_with_examples_strong_but_with_two_asterisks:
|
||||
02_01__preliminaries__tabs__001:
|
||||
# NOTE: False values are optional, they are only included here for reference. See
|
||||
# https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#glfm_example_statusyml
|
||||
# for more details.
|
||||
skip_update_example_snapshots: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
- 07_02_first_gitlab_specific_section_with_examples_strong_but_with_html:
|
||||
skip_update_example_snapshots: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
skip_update_example_snapshot_html_static: false
|
||||
skip_update_example_snapshot_html_wysiwyg: false
|
||||
skip_update_example_snapshot_prosemirror_json: false
|
||||
skip_running_conformance_static_tests: false # NOT YET SUPPORTED
|
||||
skip_running_conformance_wysiwyg_tests: false # NOT YET SUPPORTED
|
||||
skip_running_snapshot_static_html_tests: false # NOT YET SUPPORTED
|
||||
skip_running_snapshot_wysiwyg_html_tests: false # NOT YET SUPPORTED
|
||||
skip_running_snapshot_prosemirror_json_tests: false # NOT YET SUPPORTED
|
||||
|
|
|
@ -169,7 +169,6 @@ module API
|
|||
:merge_commit_template,
|
||||
:squash_commit_template,
|
||||
:repository_storage,
|
||||
:compliance_framework_setting,
|
||||
:packages_enabled,
|
||||
:service_desk_enabled,
|
||||
:keep_latest_artifact,
|
||||
|
|
|
@ -52,7 +52,7 @@ module Gitlab
|
|||
source: merge_request.source_project.try(:hook_attrs),
|
||||
target: merge_request.target_project.hook_attrs,
|
||||
last_commit: merge_request.diff_head_commit&.hook_attrs,
|
||||
work_in_progress: merge_request.work_in_progress?,
|
||||
work_in_progress: merge_request.draft?,
|
||||
total_time_spent: merge_request.total_time_spent,
|
||||
time_change: merge_request.time_change,
|
||||
human_total_time_spent: merge_request.human_total_time_spent,
|
||||
|
|
|
@ -91,7 +91,7 @@ module Gitlab
|
|||
desc 'Toggle the Draft status'
|
||||
explanation do
|
||||
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
|
||||
if quick_action_target.work_in_progress?
|
||||
if quick_action_target.draft?
|
||||
_("Unmarks this %{noun} as a draft.")
|
||||
else
|
||||
_("Marks this %{noun} as a draft.")
|
||||
|
@ -99,7 +99,7 @@ module Gitlab
|
|||
end
|
||||
execution_message do
|
||||
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
|
||||
if quick_action_target.work_in_progress?
|
||||
if quick_action_target.draft?
|
||||
_("Unmarked this %{noun} as a draft.")
|
||||
else
|
||||
_("Marked this %{noun} as a draft.")
|
||||
|
@ -108,12 +108,13 @@ module Gitlab
|
|||
|
||||
types MergeRequest
|
||||
condition do
|
||||
quick_action_target.respond_to?(:work_in_progress?) &&
|
||||
# Allow it to mark as WIP on MR creation page _or_ through MR notes.
|
||||
quick_action_target.respond_to?(:draft?) &&
|
||||
# Allow it to mark as draft on MR creation page or through MR notes
|
||||
#
|
||||
(quick_action_target.new_record? || current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target))
|
||||
end
|
||||
command :draft do
|
||||
@updates[:wip_event] = quick_action_target.work_in_progress? ? 'unwip' : 'wip'
|
||||
@updates[:wip_event] = quick_action_target.draft? ? 'unwip' : 'wip'
|
||||
end
|
||||
|
||||
desc _('Set target branch')
|
||||
|
|
|
@ -7684,6 +7684,9 @@ msgstr ""
|
|||
msgid "Checkout|Name of company or organization using GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Name: %{errors}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
|
||||
msgstr ""
|
||||
|
||||
|
@ -21828,18 +21831,9 @@ msgstr ""
|
|||
msgid "JiraService|This feature requires a Premium plan."
|
||||
msgstr ""
|
||||
|
||||
msgid "JiraService|This is a Premium feature"
|
||||
msgstr ""
|
||||
|
||||
msgid "JiraService|This is an Ultimate feature"
|
||||
msgstr ""
|
||||
|
||||
msgid "JiraService|Transition Jira issues to their final state:"
|
||||
msgstr ""
|
||||
|
||||
msgid "JiraService|Upgrade your plan to enable this feature of the Jira Integration."
|
||||
msgstr ""
|
||||
|
||||
msgid "JiraService|Use Jira as this project's issue tracker."
|
||||
msgstr ""
|
||||
|
||||
|
@ -40735,9 +40729,6 @@ msgstr ""
|
|||
msgid "Upgrade offers available!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upgrade your plan"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ module QA
|
|||
element :invite_a_group_button
|
||||
end
|
||||
|
||||
base.view 'app/assets/javascripts/invite_members/components/invite_members_trigger.vue' do
|
||||
base.view 'app/assets/javascripts/invite_members/constants.js' do
|
||||
element :invite_members_button
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ module QA
|
|||
element :invite_a_group_button
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/invite_members/components/invite_members_trigger.vue' do
|
||||
view 'app/assets/javascripts/invite_members/constants.js' do
|
||||
element :invite_members_button
|
||||
end
|
||||
|
||||
|
|
|
@ -13,6 +13,10 @@ require_relative 'parse_examples'
|
|||
# for details on the implementation and usage of this script. This developers guide
|
||||
# contains diagrams and documentation of this script,
|
||||
# including explanations and examples of all files it reads and writes.
|
||||
#
|
||||
# Also note that this script is intentionally written in a pure-functional (not OO) style,
|
||||
# with no dependencies on Rails or the GitLab libraries. These choices are intended to make
|
||||
# it faster and easier to test and debug.
|
||||
module Glfm
|
||||
class UpdateExampleSnapshots
|
||||
include Constants
|
||||
|
@ -27,28 +31,20 @@ module Glfm
|
|||
|
||||
output('(Skipping static HTML generation)') if skip_static_and_wysiwyg
|
||||
|
||||
glfm_spec_txt_lines, _glfm_examples_status_lines = read_input_files
|
||||
output("Reading #{GLFM_SPEC_TXT_PATH}...")
|
||||
glfm_spec_txt_lines = File.open(GLFM_SPEC_TXT_PATH).readlines
|
||||
|
||||
# Parse all the examples from `spec.txt`, using a Ruby port of the Python `get_tests`
|
||||
# function the from original CommonMark/GFM `spec_test.py` script.
|
||||
all_examples = parse_examples(glfm_spec_txt_lines)
|
||||
|
||||
add_example_names(all_examples)
|
||||
|
||||
write_snapshot_example_files(all_examples, skip_static_and_wysiwyg: skip_static_and_wysiwyg)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read_input_files
|
||||
[
|
||||
GLFM_SPEC_TXT_PATH,
|
||||
GLFM_EXAMPLE_STATUS_YML_PATH
|
||||
].map do |path|
|
||||
output("Reading #{path}...")
|
||||
File.open(path).readlines
|
||||
end
|
||||
end
|
||||
|
||||
def add_example_names(all_examples)
|
||||
# NOTE: This method assumes:
|
||||
# 1. Section 2 is the first section which contains examples
|
||||
|
@ -83,7 +79,7 @@ module Glfm
|
|||
formatted_headers_text = headers.join('__').tr('-', '_').tr(' ', '_').downcase
|
||||
|
||||
hierarchy_level = "#{h1_count.to_s.rjust(2, '0')}_#{h2_count.to_s.rjust(2, '0')}"
|
||||
position_within_section = index_within_h2.to_s.rjust(2, '0')
|
||||
position_within_section = index_within_h2.to_s.rjust(3, '0')
|
||||
name = "#{hierarchy_level}__#{formatted_headers_text}__#{position_within_section}"
|
||||
converted_name = name.tr('(', '').tr(')', '') # remove any parens from the name
|
||||
example[:name] = converted_name
|
||||
|
@ -91,6 +87,10 @@ module Glfm
|
|||
end
|
||||
|
||||
def write_snapshot_example_files(all_examples, skip_static_and_wysiwyg:)
|
||||
output("Reading #{GLFM_EXAMPLE_STATUS_YML_PATH}...")
|
||||
glfm_examples_statuses = YAML.safe_load(File.open(GLFM_EXAMPLE_STATUS_YML_PATH))
|
||||
validate_glfm_example_status_yml(glfm_examples_statuses)
|
||||
|
||||
write_examples_index_yml(all_examples)
|
||||
|
||||
write_markdown_yml(all_examples)
|
||||
|
@ -104,9 +104,20 @@ module Glfm
|
|||
static_html_hash = generate_static_html(markdown_yml_tempfile_path)
|
||||
wysiwyg_html_and_json_hash = generate_wysiwyg_html_and_json(markdown_yml_tempfile_path)
|
||||
|
||||
write_html_yml(all_examples, static_html_hash, wysiwyg_html_and_json_hash)
|
||||
write_html_yml(all_examples, static_html_hash, wysiwyg_html_and_json_hash, glfm_examples_statuses)
|
||||
|
||||
write_prosemirror_json_yml(all_examples, wysiwyg_html_and_json_hash)
|
||||
write_prosemirror_json_yml(all_examples, wysiwyg_html_and_json_hash, glfm_examples_statuses)
|
||||
end
|
||||
|
||||
def validate_glfm_example_status_yml(glfm_examples_statuses)
|
||||
glfm_examples_statuses.each do |example_name, statuses|
|
||||
next unless statuses &&
|
||||
statuses['skip_update_example_snapshots'] &&
|
||||
statuses.any? { |key, value| key.include?('skip_update_example_snapshot_') && !!value }
|
||||
|
||||
raise "Error: '#{example_name}' must not have any 'skip_update_example_snapshot_*' values specified " \
|
||||
"if 'skip_update_example_snapshots' is truthy"
|
||||
end
|
||||
end
|
||||
|
||||
def write_examples_index_yml(all_examples)
|
||||
|
@ -186,27 +197,77 @@ module Glfm
|
|||
YAML.load_file(wysiwyg_html_and_json_tempfile_path)
|
||||
end
|
||||
|
||||
def write_html_yml(all_examples, static_html_hash, wysiwyg_html_and_json_hash)
|
||||
generate_and_write_for_all_examples(all_examples, ES_HTML_YML_PATH) do |example, hash|
|
||||
hash[example.fetch(:name)] = {
|
||||
def write_html_yml(all_examples, static_html_hash, wysiwyg_html_and_json_hash, glfm_examples_statuses)
|
||||
generate_and_write_for_all_examples(
|
||||
all_examples, ES_HTML_YML_PATH, glfm_examples_statuses
|
||||
) do |example, hash, existing_hash|
|
||||
name = example.fetch(:name)
|
||||
example_statuses = glfm_examples_statuses[name] || {}
|
||||
|
||||
static = if example_statuses['skip_update_example_snapshot_html_static']
|
||||
existing_hash.dig(name, 'static')
|
||||
else
|
||||
static_html_hash[name]
|
||||
end
|
||||
|
||||
wysiwyg = if example_statuses['skip_update_example_snapshot_html_wysiwyg']
|
||||
existing_hash.dig(name, 'wysiwyg')
|
||||
else
|
||||
wysiwyg_html_and_json_hash.dig(name, 'html')
|
||||
end
|
||||
|
||||
hash[name] = {
|
||||
'canonical' => example.fetch(:html),
|
||||
'static' => static_html_hash.fetch(example.fetch(:name)),
|
||||
'wysiwyg' => wysiwyg_html_and_json_hash.fetch(example.fetch(:name)).fetch('html')
|
||||
}
|
||||
'static' => static,
|
||||
'wysiwyg' => wysiwyg
|
||||
}.compact # Do not assign nil values
|
||||
end
|
||||
end
|
||||
|
||||
def write_prosemirror_json_yml(all_examples, wysiwyg_html_and_json_hash)
|
||||
generate_and_write_for_all_examples(all_examples, ES_PROSEMIRROR_JSON_YML_PATH) do |example, hash|
|
||||
hash[example.fetch(:name)] = wysiwyg_html_and_json_hash.fetch(example.fetch(:name)).fetch('json')
|
||||
def write_prosemirror_json_yml(all_examples, wysiwyg_html_and_json_hash, glfm_examples_statuses)
|
||||
generate_and_write_for_all_examples(
|
||||
all_examples, ES_PROSEMIRROR_JSON_YML_PATH, glfm_examples_statuses
|
||||
) do |example, hash, existing_hash|
|
||||
name = example.fetch(:name)
|
||||
|
||||
json = if glfm_examples_statuses.dig(name, 'skip_update_example_snapshot_prosemirror_json')
|
||||
existing_hash.dig(name)
|
||||
else
|
||||
wysiwyg_html_and_json_hash.dig(name, 'json')
|
||||
end
|
||||
|
||||
# Do not assign nil values
|
||||
hash[name] = json if json
|
||||
end
|
||||
end
|
||||
|
||||
def generate_and_write_for_all_examples(all_examples, output_file_path, literal_scalars: true, &generator_block)
|
||||
output("Writing #{output_file_path}...")
|
||||
generated_examples_hash = all_examples.each_with_object({}, &generator_block)
|
||||
def generate_and_write_for_all_examples(
|
||||
all_examples, output_file_path, glfm_examples_statuses = {}, literal_scalars: true
|
||||
)
|
||||
preserve_existing = !glfm_examples_statuses.empty?
|
||||
output("#{preserve_existing ? 'Creating/Updating' : 'Creating/Overwriting'} #{output_file_path}...")
|
||||
existing_hash = preserve_existing ? YAML.safe_load(File.open(output_file_path)) : {}
|
||||
|
||||
yaml_string = dump_yaml_with_formatting(generated_examples_hash, literal_scalars: literal_scalars)
|
||||
output_hash = all_examples.each_with_object({}) do |example, hash|
|
||||
name = example.fetch(:name)
|
||||
if (reason = glfm_examples_statuses.dig(name, 'skip_update_example_snapshots'))
|
||||
# Output the reason for skipping the example, but only once, not multiple times for each file
|
||||
output("Skipping '#{name}'. Reason: #{reason}") unless glfm_examples_statuses.dig(name, :already_printed)
|
||||
# We just store the `:already_printed` flag in the hash entry itself. Then we
|
||||
# don't need an instance variable to keep the state, and this can remain a pure function ;)
|
||||
glfm_examples_statuses[name][:already_printed] = true
|
||||
|
||||
# Copy over the existing example only if it exists and preserve_existing is true, otherwise omit this example
|
||||
# noinspection RubyScope
|
||||
hash[name] = existing_hash[name] if existing_hash[name]
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
yield(example, hash, existing_hash)
|
||||
end
|
||||
|
||||
yaml_string = dump_yaml_with_formatting(output_hash, literal_scalars: literal_scalars)
|
||||
write_file(output_file_path, yaml_string)
|
||||
end
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ RSpec.describe GroupsController, factory_default: :keep do
|
|||
let_it_be(:guest) { group.add_guest(create(:user)).user }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
enable_admin_mode!(admin_with_admin_mode)
|
||||
end
|
||||
|
||||
|
|
|
@ -12,10 +12,6 @@ RSpec.describe Projects::IssuesController do
|
|||
let(:issue) { create(:issue, project: project) }
|
||||
let(:spam_action_response_fields) { { 'stub_spam_action_response_fields' => true } }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
describe "GET #index" do
|
||||
context 'external issue tracker' do
|
||||
before do
|
||||
|
|
|
@ -43,18 +43,6 @@ RSpec.describe Repositories::GitHttpController do
|
|||
post :git_upload_pack, params: params
|
||||
end
|
||||
|
||||
context 'on a read-only instance' do
|
||||
before do
|
||||
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
|
||||
end
|
||||
|
||||
it 'does not update project statistics' do
|
||||
expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async)
|
||||
|
||||
send_request
|
||||
end
|
||||
end
|
||||
|
||||
it 'updates project statistics sync for projects' do
|
||||
stub_feature_flags(disable_git_http_fetch_writes: false)
|
||||
|
||||
|
@ -83,7 +71,6 @@ RSpec.describe Repositories::GitHttpController do
|
|||
|
||||
it 'does not increment statistics' do
|
||||
expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
|
||||
expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async)
|
||||
|
||||
send_request
|
||||
end
|
||||
|
|
|
@ -7,8 +7,6 @@ RSpec.describe 'Group empty states' do
|
|||
let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
|
|
|
@ -11,10 +11,6 @@ RSpec.describe 'Group issues page' do
|
|||
let(:project_with_issues_disabled) { create(:project, :issues_disabled, group: group) }
|
||||
let(:path) { issues_group_path(group) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
context 'with shared examples', :js do
|
||||
let(:issuable) { create(:issue, project: project, title: "this is my created issuable")}
|
||||
|
||||
|
@ -140,8 +136,6 @@ RSpec.describe 'Group issues page' do
|
|||
let!(:issue3) { create(:issue, project: project, title: 'Issue #3', relative_position: 3) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: false)
|
||||
|
||||
sign_in(user_in_group)
|
||||
end
|
||||
|
||||
|
@ -164,45 +158,36 @@ RSpec.describe 'Group issues page' do
|
|||
end
|
||||
|
||||
it 'issues should be draggable and persist order' do
|
||||
visit issues_group_path(group, sort: 'relative_position')
|
||||
visit issues_group_path(group)
|
||||
select_manual_sort
|
||||
|
||||
wait_for_requests
|
||||
drag_to(selector: '.manual-ordering', from_index: 0, to_index: 2)
|
||||
|
||||
drag_to(selector: '.manual-ordering',
|
||||
from_index: 0,
|
||||
to_index: 2)
|
||||
expect_issue_order
|
||||
|
||||
wait_for_requests
|
||||
visit issues_group_path(group)
|
||||
|
||||
check_issue_order
|
||||
|
||||
visit issues_group_path(group, sort: 'relative_position')
|
||||
|
||||
check_issue_order
|
||||
expect_issue_order
|
||||
end
|
||||
|
||||
it 'issues should not be draggable when user is not logged in' do
|
||||
sign_out(user_in_group)
|
||||
|
||||
visit issues_group_path(group, sort: 'relative_position')
|
||||
|
||||
wait_for_requests
|
||||
visit issues_group_path(group)
|
||||
select_manual_sort
|
||||
|
||||
drag_to(selector: '.manual-ordering',
|
||||
from_index: 0,
|
||||
to_index: 2)
|
||||
drag_to(selector: '.manual-ordering', from_index: 0, to_index: 2)
|
||||
|
||||
wait_for_requests
|
||||
|
||||
# Issue order should remain the same
|
||||
page.within('.manual-ordering') do
|
||||
expect(find('.issue:nth-child(1) .title')).to have_content('Issue #1')
|
||||
expect(find('.issue:nth-child(2) .title')).to have_content('Issue #2')
|
||||
expect(find('.issue:nth-child(3) .title')).to have_content('Issue #3')
|
||||
end
|
||||
expect(page).to have_text 'An error occurred while reordering issues.'
|
||||
end
|
||||
|
||||
def check_issue_order
|
||||
def select_manual_sort
|
||||
click_button 'Created date'
|
||||
click_button 'Manual'
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
def expect_issue_order
|
||||
expect(page).to have_css('.issue:nth-child(1) .title', text: 'Issue #2')
|
||||
expect(page).to have_css('.issue:nth-child(2) .title', text: 'Issue #3')
|
||||
expect(page).to have_css('.issue:nth-child(3) .title', text: 'Issue #1')
|
||||
|
|
|
@ -2,23 +2,50 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Groups > User sees users dropdowns in issuables list' do
|
||||
let(:entity) { create(:group) }
|
||||
RSpec.describe 'Groups > User sees users dropdowns in issuables list', :js do
|
||||
include FilteredSearchHelpers
|
||||
|
||||
let(:group) { create(:group) }
|
||||
let(:user_in_dropdown) { create(:user) }
|
||||
let!(:user_not_in_dropdown) { create(:user) }
|
||||
let!(:project) { create(:project, group: entity) }
|
||||
let!(:project) { create(:project, group: group) }
|
||||
|
||||
before do
|
||||
entity.add_developer(user_in_dropdown)
|
||||
group.add_developer(user_in_dropdown)
|
||||
sign_in(user_in_dropdown)
|
||||
end
|
||||
|
||||
it_behaves_like 'issuable user dropdown behaviors' do
|
||||
let(:issuable) { create(:issue, project: project) }
|
||||
let(:issuables_path) { issues_group_path(entity) }
|
||||
describe 'issues' do
|
||||
let!(:issuable) { create(:issue, project: project) }
|
||||
|
||||
%w[Author Assignee].each do |dropdown|
|
||||
describe "#{dropdown} dropdown" do
|
||||
it 'only includes members of the project/group' do
|
||||
visit issues_group_path(group)
|
||||
|
||||
select_tokens dropdown, '=', submit: false
|
||||
|
||||
expect_suggestion(user_in_dropdown.name)
|
||||
expect_no_suggestion(user_not_in_dropdown.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'issuable user dropdown behaviors' do
|
||||
let(:issuable) { create(:merge_request, source_project: project) }
|
||||
let(:issuables_path) { merge_requests_group_path(entity) }
|
||||
describe 'merge requests' do
|
||||
let!(:issuable) { create(:merge_request, source_project: project) }
|
||||
|
||||
%w[author assignee].each do |dropdown|
|
||||
describe "#{dropdown} dropdown" do
|
||||
it 'only includes members of the project/group' do
|
||||
visit merge_requests_group_path(group)
|
||||
|
||||
filtered_search.set("#{dropdown}:=")
|
||||
|
||||
expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).to have_content(user_in_dropdown.name)
|
||||
expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).not_to have_content(user_not_in_dropdown.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,8 +9,6 @@ RSpec.describe 'issuable list', :js do
|
|||
issuable_types = [:issue, :merge_request]
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_user(user, :developer)
|
||||
sign_in(user)
|
||||
issuable_types.each { |type| create_issuables(type) }
|
||||
|
|
|
@ -15,10 +15,6 @@ RSpec.describe 'Issue rebalancing' do
|
|||
group.add_developer(user)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
context 'when issue rebalancing is in progress' do
|
||||
before do
|
||||
sign_in(user)
|
||||
|
|
|
@ -9,10 +9,6 @@ RSpec.describe 'Dropdown assignee', :js do
|
|||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
describe 'behavior' do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
|
|
|
@ -10,8 +10,6 @@ RSpec.describe 'Dropdown author', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@ RSpec.describe 'Dropdown base', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ RSpec.describe 'Dropdown emoji', :js do
|
|||
let_it_be(:award_emoji_star) { create(:award_emoji, name: 'star', user: user, awardable: issue) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
create_list(:award_emoji, 2, user: user, name: 'thumbsup')
|
||||
create_list(:award_emoji, 1, user: user, name: 'thumbsdown')
|
||||
|
|
|
@ -10,8 +10,6 @@ RSpec.describe 'Dropdown hint', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
end
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ RSpec.describe 'Dropdown label', :js do
|
|||
let_it_be(:label) { create(:label, project: project, title: 'bug-label') }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ RSpec.describe 'Dropdown milestone', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ RSpec.describe 'Dropdown release', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ RSpec.describe 'Filter issues', :js do
|
|||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
project.add_maintainer(user)
|
||||
|
||||
create(:issue, project: project, author: user2, title: "Bug report 1")
|
||||
|
|
|
@ -13,8 +13,6 @@ RSpec.describe 'Recent searches', :js do
|
|||
let(:project_1_local_storage_key) { "#{project_1.full_path}-issue-recent-searches" }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
# Visit any fast-loading page so we can clear local storage without a DOM exception
|
||||
visit '/404'
|
||||
remove_recent_searches
|
||||
|
|
|
@ -10,7 +10,6 @@ RSpec.describe 'Search bar', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ RSpec.describe 'Visual tokens', :js do
|
|||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
project.add_user(user, :maintainer)
|
||||
project.add_user(user_rock, :maintainer)
|
||||
sign_in(user)
|
||||
|
|
|
@ -13,10 +13,6 @@ RSpec.describe 'Project Issues RSS', :js do
|
|||
group.add_developer(user)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
context 'when signed in' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
|
|
|
@ -15,10 +15,6 @@ RSpec.describe 'Issues > Labels bulk assignment' do
|
|||
let(:issue_1_selector) { "#issuable_#{issue1.id}" }
|
||||
let(:issue_2_selector) { "#issuable_#{issue2.id}" }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
context 'as an allowed user', :js do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
|
|
|
@ -107,10 +107,6 @@ RSpec.describe 'Multiple issue updating from issues#index', :js do
|
|||
describe 'select all issues' do
|
||||
let!(:issue_2) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
it 'after selecting all issues, unchecking one issue only unselects that one issue' do
|
||||
visit project_issues_path(project)
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@ RSpec.describe "User creates issue" do
|
|||
let_it_be(:project) { create(:project_empty_repo, :public) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
end
|
||||
|
||||
context "when unauthenticated" do
|
||||
before do
|
||||
sign_out(:user)
|
||||
|
|
|
@ -7,8 +7,6 @@ RSpec.describe 'User filters issues', :js do
|
|||
let_it_be(:project) { create(:project_empty_repo, :public) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
%w[foobar barbaz].each do |title|
|
||||
create(:issue,
|
||||
author: user,
|
||||
|
|
|
@ -8,8 +8,6 @@ RSpec.describe 'New issue breadcrumb' do
|
|||
let(:user) { project.creator }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
sign_in(user)
|
||||
visit(new_project_issue_path(project))
|
||||
end
|
||||
|
|
|
@ -16,8 +16,6 @@ RSpec.describe "User sorts issues" do
|
|||
let_it_be(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
create_list(:award_emoji, 2, :upvote, awardable: issue1)
|
||||
create_list(:award_emoji, 2, :downvote, awardable: issue2)
|
||||
create(:award_emoji, :downvote, awardable: issue1)
|
||||
|
|
|
@ -17,8 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js do
|
|||
let!(:project_label_1) { create(:label, project: project_1, title: 'Label_4') }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
grandparent.add_owner(user)
|
||||
|
||||
sign_in(user)
|
||||
|
|
|
@ -17,8 +17,6 @@ RSpec.describe 'User sorts merge requests', :js do
|
|||
let_it_be(:project) { create(:project, :public, group: group) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
sign_in(user)
|
||||
|
||||
visit(project_merge_requests_path(project))
|
||||
|
|
|
@ -16,8 +16,6 @@ RSpec.describe "User sorts things", :js do
|
|||
let_it_be(:merge_request) { create(:merge_request, target_project: project, source_project: project, author: current_user) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vue_issues_list: true)
|
||||
|
||||
project.add_developer(current_user)
|
||||
sign_in(current_user)
|
||||
end
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,8 @@ const TEST_PROJECT_ID = 'abcproject';
|
|||
const TEST_MERGE_REQUEST_ID = '9001';
|
||||
const TEST_MERGE_REQUEST_URL = `${TEST_HOST}merge-requests/${TEST_MERGE_REQUEST_ID}`;
|
||||
|
||||
jest.mock('~/lib/utils/poll');
|
||||
|
||||
describe('ideStatusBar', () => {
|
||||
let store;
|
||||
let vm;
|
||||
|
|
|
@ -11,7 +11,6 @@ describe('JiraIssuesFields', () => {
|
|||
|
||||
const defaultProps = {
|
||||
showJiraVulnerabilitiesIntegration: true,
|
||||
upgradePlanPath: 'https://gitlab.com',
|
||||
};
|
||||
|
||||
const createComponent = ({
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
|
||||
|
||||
describe('JiraUpgradeCta', () => {
|
||||
let wrapper;
|
||||
|
||||
const contentMessage = 'Upgrade your plan to enable this feature of the Jira Integration.';
|
||||
|
||||
const createComponent = (propsData) => {
|
||||
wrapper = shallowMount(JiraUpgradeCta, {
|
||||
propsData,
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('displays the correct message for premium and lower users', () => {
|
||||
createComponent({ showPremiumMessage: true });
|
||||
expect(wrapper.text()).toContain('This is a Premium feature');
|
||||
expect(wrapper.text()).toContain(contentMessage);
|
||||
});
|
||||
|
||||
it('displays the correct message for ultimate and lower users', () => {
|
||||
createComponent({ showUltimateMessage: true });
|
||||
expect(wrapper.text()).toContain('This is an Ultimate feature');
|
||||
expect(wrapper.text()).toContain(contentMessage);
|
||||
});
|
||||
});
|
|
@ -2,7 +2,11 @@ import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
|
||||
import eventHub from '~/invite_members/event_hub';
|
||||
import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '~/invite_members/constants';
|
||||
import {
|
||||
TRIGGER_ELEMENT_BUTTON,
|
||||
TRIGGER_ELEMENT_SIDE_NAV,
|
||||
TRIGGER_DEFAULT_QA_SELECTOR,
|
||||
} from '~/invite_members/constants';
|
||||
|
||||
jest.mock('~/experimentation/experiment_tracking');
|
||||
|
||||
|
@ -50,12 +54,24 @@ describe.each(triggerItems)('with triggerElement as %s', (triggerItem) => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('displayText', () => {
|
||||
describe('configurable attributes', () => {
|
||||
it('includes the correct displayText for the button', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findButton().text()).toBe(displayText);
|
||||
});
|
||||
|
||||
it('uses the default qa selector value', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findButton().attributes('data-qa-selector')).toBe(TRIGGER_DEFAULT_QA_SELECTOR);
|
||||
});
|
||||
|
||||
it('sets the qa selector value', () => {
|
||||
createComponent({ qaSelector: '_qaSelector_' });
|
||||
|
||||
expect(findButton().attributes('data-qa-selector')).toBe('_qaSelector_');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clicking the link', () => {
|
||||
|
|
|
@ -746,7 +746,7 @@ eos
|
|||
end
|
||||
end
|
||||
|
||||
describe '#work_in_progress?' do
|
||||
describe '#draft?' do
|
||||
[
|
||||
'squash! ', 'fixup! ',
|
||||
'draft: ', '[Draft] ', '(draft) ', 'Draft: '
|
||||
|
@ -754,21 +754,21 @@ eos
|
|||
it "detects the '#{draft_prefix}' prefix" do
|
||||
commit.message = "#{draft_prefix}#{commit.message}"
|
||||
|
||||
expect(commit).to be_work_in_progress
|
||||
expect(commit).to be_draft
|
||||
end
|
||||
end
|
||||
|
||||
it "does not detect WIP for a commit just saying 'draft'" do
|
||||
it "does not detect a commit just saying 'draft' as draft? == true" do
|
||||
commit.message = "draft"
|
||||
|
||||
expect(commit).not_to be_work_in_progress
|
||||
expect(commit).not_to be_draft
|
||||
end
|
||||
|
||||
["FIXUP!", "Draft - ", "Wipeout", "WIP: ", "[WIP] ", "wip: "].each do |draft_prefix|
|
||||
it "doesn't detect '#{draft_prefix}' at the start of the title as a draft" do
|
||||
commit.message = "#{draft_prefix} #{commit.message}"
|
||||
|
||||
expect(commit).not_to be_work_in_progress
|
||||
expect(commit).not_to be_draft
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1381,7 +1381,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#work_in_progress?" do
|
||||
describe "#draft?" do
|
||||
subject { build_stubbed(:merge_request) }
|
||||
|
||||
[
|
||||
|
@ -1390,7 +1390,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
|||
it "detects the '#{draft_prefix}' prefix" do
|
||||
subject.title = "#{draft_prefix}#{subject.title}"
|
||||
|
||||
expect(subject.work_in_progress?).to eq true
|
||||
expect(subject.draft?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ RSpec.describe MergeRequestPresenter do
|
|||
end
|
||||
|
||||
before do
|
||||
allow(resource).to receive(:work_in_progress?).and_return(true)
|
||||
allow(resource).to receive(:draft?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when merge request enabled and has permission' do
|
||||
|
|
|
@ -2,6 +2,31 @@
|
|||
require 'fast_spec_helper'
|
||||
require_relative '../../../../scripts/lib/glfm/update_example_snapshots'
|
||||
|
||||
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/
|
||||
# for details on the implementation and usage of the `update_example_snapshots` script being tested.
|
||||
# This developers guide contains diagrams and documentation of the script,
|
||||
# including explanations and examples of all files it reads and writes.
|
||||
#
|
||||
# Note that this test is not structured in a traditional way, with multiple examples
|
||||
# to cover all different scenarios. Instead, the content of the stubbed test fixture
|
||||
# files are crafted to cover multiple scenarios with in a single example run.
|
||||
#
|
||||
# This is because the invocation of the full script is slow, because it executes
|
||||
# two subshells for processing, one which runs a full Rails environment, and one
|
||||
# which runs a jest test environment. This results in each full run of the script
|
||||
# taking between 30-60 seconds. The majority of this is spent loading the Rails environmnent.
|
||||
#
|
||||
# However, only the `writing html.yml and prosemirror_json.yml` context is used
|
||||
# to test these slow sub-processes, and it only contains a single example.
|
||||
#
|
||||
# All other tests currently in the file pass the `skip_static_and_wysiwyg: true`
|
||||
# flag to `#process`, which skips the slow sub-processes. All of these tests
|
||||
# should run in sub-second time when the Spring pre-loader is used. This allows
|
||||
# logic which is not directly related to the slow sub-processes to be TDD'd with a
|
||||
# very rapid feedback cycle.
|
||||
#
|
||||
# Also, the textual content of the individual fixture file entries is also crafted to help
|
||||
# indicate which scenarios which they are covering.
|
||||
RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
||||
subject { described_class.new }
|
||||
|
||||
|
@ -17,8 +42,10 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
let(:es_markdown_yml_path) { described_class::ES_MARKDOWN_YML_PATH }
|
||||
let(:es_markdown_yml_io) { StringIO.new }
|
||||
let(:es_html_yml_path) { described_class::ES_HTML_YML_PATH }
|
||||
let(:es_html_yml_io_existing) { StringIO.new(es_html_yml_io_existing_contents) }
|
||||
let(:es_html_yml_io) { StringIO.new }
|
||||
let(:es_prosemirror_json_yml_path) { described_class::ES_PROSEMIRROR_JSON_YML_PATH }
|
||||
let(:es_prosemirror_json_yml_io_existing) { StringIO.new(es_prosemirror_json_yml_io_existing_contents) }
|
||||
let(:es_prosemirror_json_yml_io) { StringIO.new }
|
||||
|
||||
# Internal tempfiles
|
||||
|
@ -44,7 +71,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
<p><strong>bold</strong></p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example strikethrough
|
||||
```````````````````````````````` example strong
|
||||
__bold with more text__
|
||||
.
|
||||
<p><strong>bold with more text</strong></p>
|
||||
|
@ -90,6 +117,24 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
</strong></p>
|
||||
````````````````````````````````
|
||||
|
||||
# Third GitLab-Specific Section with skipped Examples
|
||||
|
||||
## Strong but skipped
|
||||
|
||||
```````````````````````````````` example gitlab strong
|
||||
**this example will be skipped**
|
||||
.
|
||||
<p><strong>this example will be skipped</strong></p>
|
||||
````````````````````````````````
|
||||
|
||||
## Strong but manually modified and skipped
|
||||
|
||||
```````````````````````````````` example gitlab strong
|
||||
**This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved**
|
||||
.
|
||||
<p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p>
|
||||
````````````````````````````````
|
||||
|
||||
<!-- END TESTS -->
|
||||
|
||||
# Appendix
|
||||
|
@ -99,25 +144,90 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
end
|
||||
|
||||
let(:glfm_example_status_yml_contents) do
|
||||
# language=YAML
|
||||
<<~GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
---
|
||||
- 07_01_first_gitlab_specific_section_with_examples_strong_but_with_two_asterisks:
|
||||
02_01__inlines__strong__001:
|
||||
# The skip_update_example_snapshots key is present, but false, so this example is not skipped
|
||||
skip_update_example_snapshots: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
- 07_02_first_gitlab_specific_section_with_examples_strong_but_with_html:
|
||||
skip_update_example_snapshots: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
02_01__inlines__strong__002:
|
||||
# It is OK to have an empty (nil) value for an example statuses entry, it means they will all be false.
|
||||
05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001:
|
||||
# Always skip this example
|
||||
skip_update_example_snapshots: 'skipping this example because it is very bad'
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
|
||||
# Always skip this example, but preserve the existing manual modifications
|
||||
skip_update_example_snapshots: 'skipping this example because we have manually modified it'
|
||||
GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
end
|
||||
|
||||
let(:es_html_yml_io_existing_contents) do
|
||||
# language=YAML
|
||||
<<~ES_HTML_YML_IO_EXISTING_CONTENTS
|
||||
---
|
||||
00_00__obsolete_entry_to_be_deleted__001:
|
||||
canonical: |
|
||||
This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted.
|
||||
static: |-
|
||||
This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted.
|
||||
wysiwyg: |-
|
||||
This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted.
|
||||
02_01__inlines__strong__001:
|
||||
canonical: |
|
||||
This entry is existing, but not skipped, so it will be overwritten.
|
||||
static: |-
|
||||
This entry is existing, but not skipped, so it will be overwritten.
|
||||
wysiwyg: |-
|
||||
This entry is existing, but not skipped, so it will be overwritten.
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
|
||||
canonical: |
|
||||
<p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p>
|
||||
static: |-
|
||||
<p>This is the manually modified static HTML which will be preserved</p>
|
||||
wysiwyg: |-
|
||||
<p>This is the manually modified WYSIWYG HTML which will be preserved</p>
|
||||
ES_HTML_YML_IO_EXISTING_CONTENTS
|
||||
end
|
||||
|
||||
let(:es_prosemirror_json_yml_io_existing_contents) do
|
||||
# language=YAML
|
||||
<<~ES_PROSEMIRROR_JSON_YML_IO_EXISTING_CONTENTS
|
||||
---
|
||||
00_00__obsolete_entry_to_be_deleted__001:
|
||||
{
|
||||
"obsolete": "This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted."
|
||||
}
|
||||
02_01__inlines__strong__001: |-
|
||||
{
|
||||
"existing": "This entry is existing, but not skipped, so it will be overwritten."
|
||||
}
|
||||
# 02_01__inlines__strong__002: is omitted from the existing file and skipped, to test that scenario.
|
||||
02_02__inlines__strikethrough_extension__001: |-
|
||||
{
|
||||
"type": "doc",
|
||||
"content": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "~~Hi~~ Hello, world!"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |-
|
||||
{
|
||||
"existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy"
|
||||
}
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |-
|
||||
{
|
||||
"existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy"
|
||||
}
|
||||
ES_PROSEMIRROR_JSON_YML_IO_EXISTING_CONTENTS
|
||||
end
|
||||
|
||||
before do
|
||||
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
|
||||
# objects. This gives better and more realistic coverage, while still avoiding
|
||||
|
@ -129,12 +239,14 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
|
||||
# output files
|
||||
allow(File).to receive(:open).with(es_examples_index_yml_path, 'w') { es_examples_index_yml_io }
|
||||
allow(File).to receive(:open).with(es_html_yml_path, 'w') { es_html_yml_io }
|
||||
allow(File).to receive(:open).with(es_prosemirror_json_yml_path, 'w') { es_prosemirror_json_yml_io }
|
||||
|
||||
# output files which are also input files
|
||||
allow(File).to receive(:open).with(es_markdown_yml_path, 'w') { es_markdown_yml_io }
|
||||
allow(File).to receive(:open).with(es_markdown_yml_path) { es_markdown_yml_io }
|
||||
allow(File).to receive(:open).with(es_html_yml_path, 'w') { es_html_yml_io }
|
||||
allow(File).to receive(:open).with(es_html_yml_path) { es_html_yml_io_existing }
|
||||
allow(File).to receive(:open).with(es_prosemirror_json_yml_path, 'w') { es_prosemirror_json_yml_io }
|
||||
allow(File).to receive(:open).with(es_prosemirror_json_yml_path) { es_prosemirror_json_yml_io_existing }
|
||||
|
||||
# Allow normal opening of Tempfile files created during script execution.
|
||||
tempfile_basenames = [
|
||||
|
@ -152,26 +264,71 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
allow(subject).to receive(:output)
|
||||
end
|
||||
|
||||
describe 'when skip_update_example_snapshots is truthy' do
|
||||
let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) }
|
||||
let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) }
|
||||
let(:expected_unskipped_example) do
|
||||
/05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001/
|
||||
end
|
||||
|
||||
it 'still writes the example to examples_index.yml' do
|
||||
subject.process(skip_static_and_wysiwyg: true)
|
||||
|
||||
expect(es_examples_index_yml_contents).to match(expected_unskipped_example)
|
||||
end
|
||||
|
||||
it 'still writes the example to markdown.yml' do
|
||||
subject.process(skip_static_and_wysiwyg: true)
|
||||
|
||||
expect(es_markdown_yml_contents).to match(expected_unskipped_example)
|
||||
end
|
||||
|
||||
describe 'when any other skip_update_example_* is also truthy' do
|
||||
let(:glfm_example_status_yml_contents) do
|
||||
# language=YAML
|
||||
<<~GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
---
|
||||
02_01__inlines__strong__001:
|
||||
skip_update_example_snapshots: 'if the skip_update_example_snapshots key is truthy...'
|
||||
skip_update_example_snapshot_html_static: '...then no other skip_update_example_* keys can be truthy'
|
||||
GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
expected_msg = "Error: '02_01__inlines__strong__001' must not have any 'skip_update_example_snapshot_*' " \
|
||||
"values specified if 'skip_update_example_snapshots' is truthy"
|
||||
expect { subject.process }.to raise_error(/#{Regexp.escape(expected_msg)}/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'writing examples_index.yml' do
|
||||
let(:es_examples_index_yml_contents) { reread_io(es_examples_index_yml_io) }
|
||||
let(:expected_examples_index_yml_contents) do
|
||||
# language=YAML
|
||||
<<~ES_EXAMPLES_INDEX_YML_CONTENTS
|
||||
---
|
||||
02_01__inlines__strong__01:
|
||||
02_01__inlines__strong__001:
|
||||
spec_txt_example_position: 1
|
||||
source_specification: commonmark
|
||||
02_01__inlines__strong__02:
|
||||
02_01__inlines__strong__002:
|
||||
spec_txt_example_position: 2
|
||||
source_specification: github
|
||||
02_02__inlines__strikethrough_extension__01:
|
||||
02_02__inlines__strikethrough_extension__001:
|
||||
spec_txt_example_position: 3
|
||||
source_specification: github
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01:
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
|
||||
spec_txt_example_position: 4
|
||||
source_specification: gitlab
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__01:
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
|
||||
spec_txt_example_position: 5
|
||||
source_specification: gitlab
|
||||
05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001:
|
||||
spec_txt_example_position: 6
|
||||
source_specification: gitlab
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
|
||||
spec_txt_example_position: 7
|
||||
source_specification: gitlab
|
||||
ES_EXAMPLES_INDEX_YML_CONTENTS
|
||||
end
|
||||
|
||||
|
@ -185,20 +342,25 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
describe 'writing markdown.yml' do
|
||||
let(:es_markdown_yml_contents) { reread_io(es_markdown_yml_io) }
|
||||
let(:expected_markdown_yml_contents) do
|
||||
# language=YAML
|
||||
<<~ES_MARKDOWN_YML_CONTENTS
|
||||
---
|
||||
02_01__inlines__strong__01: |
|
||||
02_01__inlines__strong__001: |
|
||||
__bold__
|
||||
02_01__inlines__strong__02: |
|
||||
02_01__inlines__strong__002: |
|
||||
__bold with more text__
|
||||
02_02__inlines__strikethrough_extension__01: |
|
||||
02_02__inlines__strikethrough_extension__001: |
|
||||
~~Hi~~ Hello, world!
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: |
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |
|
||||
**bold**
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__01: |
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |
|
||||
<strong>
|
||||
bold
|
||||
</strong>
|
||||
05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001: |
|
||||
**this example will be skipped**
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |
|
||||
**This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved**
|
||||
ES_MARKDOWN_YML_CONTENTS
|
||||
end
|
||||
|
||||
|
@ -213,61 +375,78 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
let(:es_html_yml_contents) { reread_io(es_html_yml_io) }
|
||||
let(:es_prosemirror_json_yml_contents) { reread_io(es_prosemirror_json_yml_io) }
|
||||
|
||||
# NOTE: This example_status.yml is crafted in conjunction with expected_html_yml_contents
|
||||
# to test the behavior of the `skip_update_*` flags
|
||||
let(:glfm_example_status_yml_contents) do
|
||||
# language=YAML
|
||||
<<~GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
---
|
||||
- 02_01_gitlab_specific_section_with_examples_strong_but_with_two_asterisks:
|
||||
skip_update_example_snapshots: false
|
||||
skip_running_snapshot_static_html_tests: false
|
||||
skip_running_snapshot_wysiwyg_html_tests: false
|
||||
skip_running_snapshot_prosemirror_json_tests: false
|
||||
skip_running_conformance_static_tests: false
|
||||
skip_running_conformance_wysiwyg_tests: false
|
||||
02_01__inlines__strong__002:
|
||||
skip_update_example_snapshot_prosemirror_json: "skipping because JSON isn't cool enough"
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
|
||||
skip_update_example_snapshot_html_static: "skipping because there's too much static"
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
|
||||
skip_update_example_snapshot_html_wysiwyg: 'skipping because what you see is NOT what you get'
|
||||
skip_update_example_snapshot_prosemirror_json: "skipping because JSON still isn't cool enough"
|
||||
05_01__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001:
|
||||
skip_update_example_snapshots: 'skipping this example because it is very bad'
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
|
||||
skip_update_example_snapshots: 'skipping this example because we have manually modified it'
|
||||
GLFM_EXAMPLE_STATUS_YML_CONTENTS
|
||||
end
|
||||
|
||||
let(:glfm_spec_txt_contents) do
|
||||
<<~GLFM_SPEC_TXT_CONTENTS
|
||||
---
|
||||
title: GitLab Flavored Markdown Spec
|
||||
...
|
||||
|
||||
# Introduction
|
||||
|
||||
# GitLab-Specific Section with Examples
|
||||
|
||||
## Strong but with two asterisks
|
||||
|
||||
```````````````````````````````` example gitlab strong
|
||||
**bold**
|
||||
.
|
||||
<p><strong>bold</strong></p>
|
||||
````````````````````````````````
|
||||
<!-- END TESTS -->
|
||||
|
||||
# Appendix
|
||||
|
||||
Appendix text.
|
||||
GLFM_SPEC_TXT_CONTENTS
|
||||
end
|
||||
|
||||
let(:expected_html_yml_contents) do
|
||||
# language=YAML
|
||||
<<~ES_HTML_YML_CONTENTS
|
||||
---
|
||||
02_01__gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01:
|
||||
02_01__inlines__strong__001:
|
||||
canonical: |
|
||||
<p><strong>bold</strong></p>
|
||||
static: |-
|
||||
<p data-sourcepos="1:1-1:8" dir="auto"><strong>bold</strong></p>
|
||||
wysiwyg: |-
|
||||
<p><strong>bold</strong></p>
|
||||
02_01__inlines__strong__002:
|
||||
canonical: |
|
||||
<p><strong>bold with more text</strong></p>
|
||||
static: |-
|
||||
<p data-sourcepos="1:1-1:23" dir="auto"><strong>bold with more text</strong></p>
|
||||
wysiwyg: |-
|
||||
<p><strong>bold with more text</strong></p>
|
||||
02_02__inlines__strikethrough_extension__001:
|
||||
canonical: |
|
||||
<p><del>Hi</del> Hello, world!</p>
|
||||
static: |-
|
||||
<p data-sourcepos="1:1-1:20" dir="auto"><del>Hi</del> Hello, world!</p>
|
||||
wysiwyg: |-
|
||||
<p>~~Hi~~ Hello, world!</p>
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
|
||||
canonical: |
|
||||
<p><strong>bold</strong></p>
|
||||
wysiwyg: |-
|
||||
<p><strong>bold</strong></p>
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
|
||||
canonical: |
|
||||
<p><strong>
|
||||
bold
|
||||
</strong></p>
|
||||
static: |-
|
||||
<strong>
bold
</strong>
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
|
||||
canonical: |
|
||||
<p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p>
|
||||
static: |-
|
||||
<p>This is the manually modified static HTML which will be preserved</p>
|
||||
wysiwyg: |-
|
||||
<p>This is the manually modified WYSIWYG HTML which will be preserved</p>
|
||||
ES_HTML_YML_CONTENTS
|
||||
end
|
||||
|
||||
let(:expected_prosemirror_json_contents) do
|
||||
# language=YAML
|
||||
<<~ES_PROSEMIRROR_JSON_YML_CONTENTS
|
||||
---
|
||||
02_01__gitlab_specific_section_with_examples__strong_but_with_two_asterisks__01: |-
|
||||
02_01__inlines__strong__001: |-
|
||||
{
|
||||
"type": "doc",
|
||||
"content": [
|
||||
|
@ -287,6 +466,49 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
}
|
||||
]
|
||||
}
|
||||
02_02__inlines__strikethrough_extension__001: |-
|
||||
{
|
||||
"type": "doc",
|
||||
"content": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "~~Hi~~ Hello, world!"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
03_01__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |-
|
||||
{
|
||||
"type": "doc",
|
||||
"content": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"marks": [
|
||||
{
|
||||
"type": "bold"
|
||||
}
|
||||
],
|
||||
"text": "bold"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
04_01__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |-
|
||||
{
|
||||
"existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy"
|
||||
}
|
||||
05_02__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |-
|
||||
{
|
||||
"existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy"
|
||||
}
|
||||
ES_PROSEMIRROR_JSON_YML_CONTENTS
|
||||
end
|
||||
|
||||
|
@ -304,6 +526,9 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
|
|||
# the rails environment. We could have separate sections, but this would require an extra flag
|
||||
# to the `process` method to independently skip static vs. WYSIWYG, which is not worth the effort.
|
||||
it 'writes the correct content' do
|
||||
# expectation that skipping message is only output once per example
|
||||
expect(subject).to receive(:output).once.with(/reason.*skipping this example because it is very bad/i)
|
||||
|
||||
subject.process
|
||||
|
||||
expect(es_html_yml_contents).to eq(expected_html_yml_contents)
|
||||
|
|
|
@ -32,7 +32,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
|
|||
|
||||
it 'creates an MR' do
|
||||
expect(merge_request).to be_valid
|
||||
expect(merge_request.work_in_progress?).to be(false)
|
||||
expect(merge_request.draft?).to be(false)
|
||||
expect(merge_request.title).to eq('Awesome merge_request')
|
||||
expect(merge_request.assignees).to be_empty
|
||||
expect(merge_request.merge_params['force_remove_source_branch']).to eq('1')
|
||||
|
@ -74,7 +74,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
|
|||
end
|
||||
|
||||
it 'sets MR to draft' do
|
||||
expect(merge_request.work_in_progress?).to be(true)
|
||||
expect(merge_request.draft?).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -90,7 +90,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
|
|||
end
|
||||
|
||||
it 'sets MR to draft' do
|
||||
expect(merge_request.work_in_progress?).to be(true)
|
||||
expect(merge_request.draft?).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -756,47 +756,48 @@ RSpec.describe MergeRequests::RefreshService do
|
|||
refresh_service.execute(oldrev, newrev, 'refs/heads/wip')
|
||||
fixup_merge_request.reload
|
||||
|
||||
expect(fixup_merge_request.work_in_progress?).to eq(true)
|
||||
expect(fixup_merge_request.draft?).to eq(true)
|
||||
expect(fixup_merge_request.notes.last.note).to match(
|
||||
/marked this merge request as \*\*draft\*\* from #{Commit.reference_pattern}/
|
||||
)
|
||||
end
|
||||
|
||||
it 'references the commit that caused the draft status' do
|
||||
wip_merge_request = create(:merge_request,
|
||||
draft_merge_request = create(:merge_request,
|
||||
source_project: @project,
|
||||
source_branch: 'wip',
|
||||
target_branch: 'master',
|
||||
target_project: @project)
|
||||
|
||||
commits = wip_merge_request.commits
|
||||
commits = draft_merge_request.commits
|
||||
oldrev = commits.last.id
|
||||
newrev = commits.first.id
|
||||
wip_commit = wip_merge_request.commits.find(&:work_in_progress?)
|
||||
draft_commit = draft_merge_request.commits.find(&:draft?)
|
||||
|
||||
refresh_service.execute(oldrev, newrev, 'refs/heads/wip')
|
||||
|
||||
expect(wip_merge_request.reload.notes.last.note).to eq(
|
||||
"marked this merge request as **draft** from #{wip_commit.id}"
|
||||
expect(draft_merge_request.reload.notes.last.note).to eq(
|
||||
"marked this merge request as **draft** from #{draft_commit.id}"
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not mark as draft based on commits that do not belong to an MR' do
|
||||
allow(refresh_service).to receive(:find_new_commits)
|
||||
|
||||
refresh_service.instance_variable_set("@commits", [
|
||||
double(
|
||||
id: 'aaaaaaa',
|
||||
sha: 'aaaaaaa',
|
||||
short_id: 'aaaaaaa',
|
||||
title: 'Fix issue',
|
||||
work_in_progress?: false
|
||||
draft?: false
|
||||
),
|
||||
double(
|
||||
id: 'bbbbbbb',
|
||||
sha: 'bbbbbbbb',
|
||||
short_id: 'bbbbbbb',
|
||||
title: 'fixup! Fix issue',
|
||||
work_in_progress?: true,
|
||||
draft?: true,
|
||||
to_reference: 'bbbbbbb'
|
||||
)
|
||||
])
|
||||
|
@ -804,7 +805,7 @@ RSpec.describe MergeRequests::RefreshService do
|
|||
refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
|
||||
reload_mrs
|
||||
|
||||
expect(@merge_request.work_in_progress?).to be_falsey
|
||||
expect(@merge_request.draft?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -359,7 +359,7 @@ RSpec.describe Notes::CreateService do
|
|||
issuable.reload.update!(title: "title")
|
||||
},
|
||||
expectation: ->(issuable, can_use_quick_action) {
|
||||
expect(issuable.work_in_progress?).to eq(can_use_quick_action)
|
||||
expect(issuable.draft?).to eq(can_use_quick_action)
|
||||
}
|
||||
),
|
||||
# Remove draft status
|
||||
|
@ -369,7 +369,7 @@ RSpec.describe Notes::CreateService do
|
|||
issuable.reload.update!(title: "Draft: title")
|
||||
},
|
||||
expectation: ->(noteable, can_use_quick_action) {
|
||||
expect(noteable.work_in_progress?).not_to eq(can_use_quick_action)
|
||||
expect(noteable.draft?).not_to eq(can_use_quick_action)
|
||||
}
|
||||
)
|
||||
]
|
||||
|
|
|
@ -308,10 +308,6 @@ RSpec.configure do |config|
|
|||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/33867
|
||||
stub_feature_flags(file_identifier_hash: false)
|
||||
|
||||
# The following `vue_issues_list` stub can be removed
|
||||
# once the Vue issues page has feature parity with the current Haml page
|
||||
stub_feature_flags(vue_issues_list: false)
|
||||
|
||||
# Disable `main_branch_over_master` as we migrate
|
||||
# from `master` to `main` accross our codebase.
|
||||
# It's done in order to preserve the concistency in tests
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'issuable user dropdown behaviors' do
|
||||
include FilteredSearchHelpers
|
||||
|
||||
before do
|
||||
issuable # ensure we have at least one issuable
|
||||
sign_in(user_in_dropdown)
|
||||
end
|
||||
|
||||
%w[author assignee].each do |dropdown|
|
||||
describe "#{dropdown} dropdown", :js do
|
||||
it 'only includes members of the project/group' do
|
||||
visit issuables_path
|
||||
|
||||
filtered_search.set("#{dropdown}:=")
|
||||
|
||||
expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).to have_content(user_in_dropdown.name)
|
||||
expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).not_to have_content(user_not_in_dropdown.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -378,7 +378,6 @@ RSpec.describe 'Every Sidekiq worker' do
|
|||
'PostReceive' => 3,
|
||||
'ProcessCommitWorker' => 3,
|
||||
'ProjectCacheWorker' => 3,
|
||||
'ProjectDailyStatisticsWorker' => 3,
|
||||
'ProjectDestroyWorker' => 3,
|
||||
'ProjectExportWorker' => false,
|
||||
'ProjectImportScheduleWorker' => 1,
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ProjectDailyStatisticsWorker, '#perform' do
|
||||
let(:worker) { described_class.new }
|
||||
let(:project) { create(:project) }
|
||||
|
||||
describe '#perform' do
|
||||
context 'with a non-existing project' do
|
||||
it 'does nothing' do
|
||||
expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
|
||||
|
||||
worker.perform(-1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an existing project without a repository' do
|
||||
it 'does nothing' do
|
||||
expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
|
||||
|
||||
worker.perform(project.id)
|
||||
end
|
||||
end
|
||||
|
||||
it 'calls daily_statistics_service with the given project' do
|
||||
project = create(:project, :repository)
|
||||
|
||||
expect_next_instance_of(Projects::FetchStatisticsIncrementService, project) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
end
|
||||
|
||||
worker.perform(project.id)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue