Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
01fbd09ea9
commit
866b1f8ed7
|
@ -1 +1 @@
|
|||
e1dd9bfe694190e9350dad37b5cd8b5ea44eafa3
|
||||
bb32df05c777d0cd8a8d15249c99e2d8055e0769
|
||||
|
|
|
@ -104,18 +104,13 @@ export default {
|
|||
@[$options.EVENT_ERROR]="onError"
|
||||
@[$options.EVENT_SUCCESS]="onSuccess"
|
||||
>
|
||||
<div ref="container">
|
||||
<div ref="container" data-testid="access-token-section" data-qa-selector="access_token_section">
|
||||
<template v-if="newToken">
|
||||
<!--
|
||||
After issue https://gitlab.com/gitlab-org/gitlab/-/issues/360921 is
|
||||
closed remove the `initial-visibility`.
|
||||
-->
|
||||
<input-copy-toggle-visibility
|
||||
:copy-button-title="copyButtonTitle"
|
||||
:label="label"
|
||||
:label-for="$options.tokenInputId"
|
||||
:value="newToken"
|
||||
initial-visibility
|
||||
:form-input-group-props="formInputGroupProps"
|
||||
>
|
||||
<template #description>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import initSearchSettings from '~/search_settings';
|
||||
import initWebhookForm from '~/webhooks';
|
||||
import { initPushEventsEditForm } from '~/webhooks/webhook';
|
||||
|
||||
initSearchSettings();
|
||||
initWebhookForm();
|
||||
initPushEventsEditForm();
|
||||
|
|
|
@ -129,6 +129,8 @@ export default {
|
|||
v-gl-tooltip.hover="toggleVisibilityLabel"
|
||||
:aria-label="toggleVisibilityLabel"
|
||||
:icon="toggleVisibilityIcon"
|
||||
data-testid="toggle-visibility-button"
|
||||
data-qa-selector="toggle_visibility_button"
|
||||
@click.stop="handleToggleVisibilityButtonClick"
|
||||
/>
|
||||
<clipboard-button
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<script>
|
||||
import { GlFormCheckbox, GlFormRadio, GlFormRadioGroup, GlFormInput, GlSprintf } from '@gitlab/ui';
|
||||
import {
|
||||
BRANCH_FILTER_ALL_BRANCHES,
|
||||
WILDCARD_CODE_STABLE,
|
||||
WILDCARD_CODE_PRODUCTION,
|
||||
REGEX_CODE,
|
||||
descriptionText,
|
||||
} from '~/webhooks/constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlFormCheckbox,
|
||||
GlFormRadio,
|
||||
GlFormRadioGroup,
|
||||
GlFormInput,
|
||||
GlSprintf,
|
||||
},
|
||||
inject: ['pushEvents', 'strategy', 'isNewHook', 'pushEventsBranchFilter'],
|
||||
data() {
|
||||
return {
|
||||
pushEventsData: !this.isNewHook && this.pushEvents,
|
||||
branchFilterStrategyData: this.isNewHook ? BRANCH_FILTER_ALL_BRANCHES : this.strategy,
|
||||
pushEventsBranchFilterData: this.pushEventsBranchFilter,
|
||||
};
|
||||
},
|
||||
WILDCARD_CODE_STABLE,
|
||||
WILDCARD_CODE_PRODUCTION,
|
||||
REGEX_CODE,
|
||||
descriptionText,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<gl-form-checkbox v-model="pushEventsData">{{ s__('Webhooks|Push events') }}</gl-form-checkbox>
|
||||
<input type="hidden" :value="pushEventsData" name="hook[push_events]" />
|
||||
|
||||
<div v-if="pushEventsData" class="gl-pl-6">
|
||||
<gl-form-radio-group v-model="branchFilterStrategyData" name="hook[branch_filter_strategy]">
|
||||
<gl-form-radio
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
value="all_branches"
|
||||
data-testid="rule_all_branches"
|
||||
>
|
||||
<div data-qa-selector="strategy_radio_all">{{ __('All branches') }}</div>
|
||||
</gl-form-radio>
|
||||
|
||||
<!-- wildcard -->
|
||||
<gl-form-radio
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
value="wildcard"
|
||||
data-testid="rule_wildcard"
|
||||
>
|
||||
<div data-qa-selector="strategy_radio_wildcard">
|
||||
{{ s__('Webhooks|Wildcard pattern') }}
|
||||
</div>
|
||||
</gl-form-radio>
|
||||
<div class="gl-ml-6">
|
||||
<gl-form-input
|
||||
v-if="branchFilterStrategyData === 'wildcard'"
|
||||
v-model="pushEventsBranchFilterData"
|
||||
name="hook[push_events_branch_filter]"
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
v-if="branchFilterStrategyData === 'wildcard'"
|
||||
class="form-text text-muted custom-control"
|
||||
>
|
||||
<gl-sprintf :message="$options.descriptionText.wildcard">
|
||||
<template #WILDCARD_CODE_STABLE>
|
||||
<code>{{ $options.WILDCARD_CODE_STABLE }}</code>
|
||||
</template>
|
||||
<template #WILDCARD_CODE_PRODUCTION>
|
||||
<code>{{ $options.WILDCARD_CODE_PRODUCTION }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
|
||||
<!-- regex -->
|
||||
<gl-form-radio
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
value="regex"
|
||||
data-testid="rule_regex"
|
||||
>
|
||||
<div data-qa-selector="strategy_radio_regex">
|
||||
{{ s__('Webhooks|Regular expression') }}
|
||||
</div>
|
||||
</gl-form-radio>
|
||||
<div class="gl-ml-6">
|
||||
<gl-form-input
|
||||
v-if="branchFilterStrategyData === 'regex'"
|
||||
v-model="pushEventsBranchFilterData"
|
||||
name="hook[push_events_branch_filter]"
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p v-if="branchFilterStrategyData === 'regex'" class="form-text text-muted custom-control">
|
||||
<gl-sprintf :message="$options.descriptionText.regex">
|
||||
<template #REGEX_CODE>
|
||||
<code>{{ $options.REGEX_CODE }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</gl-form-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,17 @@
|
|||
import { s__ } from '~/locale';
|
||||
|
||||
export const BRANCH_FILTER_ALL_BRANCHES = 'all_branches';
|
||||
export const BRANCH_FILTER_WILDCARD = 'wildcard';
|
||||
export const BRANCH_FILTER_REGEX = 'regex';
|
||||
|
||||
export const WILDCARD_CODE_STABLE = '*-stable';
|
||||
export const WILDCARD_CODE_PRODUCTION = 'production/*';
|
||||
|
||||
export const REGEX_CODE = '(feature|hotfix)/*';
|
||||
|
||||
export const descriptionText = {
|
||||
[BRANCH_FILTER_WILDCARD]: s__(
|
||||
'Webhooks|Wildcards such as %{WILDCARD_CODE_STABLE} or %{WILDCARD_CODE_PRODUCTION} are supported.',
|
||||
),
|
||||
[BRANCH_FILTER_REGEX]: s__('Webhooks|Regex such as %{REGEX_CODE} is supported.'),
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
import Vue from 'vue';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import pushEvents from './components/push_events.vue';
|
||||
|
||||
export function initPushEventsEditForm() {
|
||||
const el = document.querySelector('.js-vue-push-events');
|
||||
|
||||
if (!el) return false;
|
||||
|
||||
const provide = {
|
||||
isNewHook: parseBoolean(el.dataset.isNewHook),
|
||||
pushEvents: parseBoolean(el.dataset.pushEvents),
|
||||
strategy: el.dataset.strategy,
|
||||
pushEventsBranchFilter: el.dataset.pushEventsBranchFilter,
|
||||
};
|
||||
return new Vue({
|
||||
el,
|
||||
provide,
|
||||
render(createElement) {
|
||||
return createElement(pushEvents);
|
||||
},
|
||||
});
|
||||
}
|
|
@ -68,7 +68,7 @@ module EventsHelper
|
|||
author = event.author
|
||||
|
||||
if author
|
||||
name = self_added ? 'You' : author.name
|
||||
name = self_added ? _('You') : author.name
|
||||
link_to name, user_path(author.username), title: name
|
||||
else
|
||||
escape_once(event.author_name)
|
||||
|
|
|
@ -160,6 +160,31 @@ module IntegrationsHelper
|
|||
!Gitlab.com?
|
||||
end
|
||||
|
||||
def integration_issue_type(issue_type)
|
||||
issue_type_i18n_map = {
|
||||
'issue' => _('Issue'),
|
||||
'incident' => _('Incident'),
|
||||
'test_case' => _('Test case'),
|
||||
'requirement' => _('Requirement'),
|
||||
'task' => _('Task')
|
||||
}
|
||||
|
||||
issue_type_i18n_map[issue_type] || issue_type
|
||||
end
|
||||
|
||||
def integration_todo_target_type(target_type)
|
||||
target_type_i18n_map = {
|
||||
'Commit' => _('Commit'),
|
||||
'Issue' => _('Issue'),
|
||||
'MergeRequest' => _('Merge Request'),
|
||||
'Epic' => _('Epic'),
|
||||
DesignManagement::Design.name => _('design'),
|
||||
AlertManagement::Alert.name => _('alert')
|
||||
}
|
||||
|
||||
target_type_i18n_map[target_type] || target_type
|
||||
end
|
||||
|
||||
extend self
|
||||
|
||||
private
|
||||
|
|
|
@ -15,21 +15,25 @@ module TodosHelper
|
|||
|
||||
def todo_action_name(todo)
|
||||
case todo.action
|
||||
when Todo::ASSIGNED then todo.self_added? ? 'assigned' : 'assigned you'
|
||||
when Todo::REVIEW_REQUESTED then 'requested a review of'
|
||||
when Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED then "mentioned #{todo_action_subject(todo)} on"
|
||||
when Todo::BUILD_FAILED then 'The pipeline failed in'
|
||||
when Todo::MARKED then 'added a todo for'
|
||||
when Todo::APPROVAL_REQUIRED then "set #{todo_action_subject(todo)} as an approver for"
|
||||
when Todo::UNMERGEABLE then 'Could not merge'
|
||||
when Todo::MERGE_TRAIN_REMOVED then "Removed from Merge Train:"
|
||||
when Todo::ASSIGNED then todo.self_added? ? _('assigned') : _('assigned you')
|
||||
when Todo::REVIEW_REQUESTED then s_('Todos|requested a review of')
|
||||
when Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED then format(
|
||||
s_("Todos|mentioned %{who} on"), who: todo_action_subject(todo)
|
||||
)
|
||||
when Todo::BUILD_FAILED then s_('Todos|The pipeline failed in')
|
||||
when Todo::MARKED then s_('Todos|added a todo for')
|
||||
when Todo::APPROVAL_REQUIRED then format(
|
||||
s_("Todos|set %{who} as an approver for"), who: todo_action_subject(todo)
|
||||
)
|
||||
when Todo::UNMERGEABLE then s_('Todos|Could not merge')
|
||||
when Todo::MERGE_TRAIN_REMOVED then s_("Todos|Removed from Merge Train:")
|
||||
end
|
||||
end
|
||||
|
||||
def todo_self_addressing(todo)
|
||||
case todo.action
|
||||
when Todo::ASSIGNED then 'to yourself'
|
||||
when Todo::REVIEW_REQUESTED then 'from yourself'
|
||||
when Todo::ASSIGNED then _('to yourself')
|
||||
when Todo::REVIEW_REQUESTED then _('from yourself')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,9 +70,9 @@ module TodosHelper
|
|||
return _('alert') if todo.for_alert?
|
||||
|
||||
target_type = if todo.for_issue_or_work_item?
|
||||
todo.target.issue_type
|
||||
IntegrationsHelper.integration_issue_type(todo.target.issue_type)
|
||||
else
|
||||
todo.target_type
|
||||
IntegrationsHelper.integration_todo_target_type(todo.target_type)
|
||||
end
|
||||
|
||||
target_type.titleize.downcase
|
||||
|
@ -109,6 +113,11 @@ module TodosHelper
|
|||
return unless show_todo_state?(todo)
|
||||
|
||||
state = todo.target.state.to_s
|
||||
raw_state_to_i18n = {
|
||||
"closed" => _('Closed'),
|
||||
"merged" => _('Merged'),
|
||||
"resolved" => _('Resolved')
|
||||
}
|
||||
|
||||
case todo.target
|
||||
when MergeRequest
|
||||
|
@ -124,7 +133,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
tag.span class: "gl-my-0 gl-px-2 status-box #{background_class}" do
|
||||
todo.target.state.to_s.capitalize
|
||||
raw_state_to_i18n[state] || state.capitalize
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -237,7 +246,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def todo_action_subject(todo)
|
||||
todo.self_added? ? 'yourself' : 'you'
|
||||
todo.self_added? ? s_('Todos|yourself') : _('you')
|
||||
end
|
||||
|
||||
def show_todo_state?(todo)
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
= todo_target_title(todo)
|
||||
|
||||
%span.title-item.todo-project.todo-label
|
||||
at
|
||||
= todo_parent_path(todo)
|
||||
= s_('Todo|at %{todo_parent_path}').html_safe % { todo_parent_path: todo_parent_path(todo) }
|
||||
|
||||
- if todo.self_assigned?
|
||||
%span.title-item.action-name
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FinalizeInvalidMemberCleanup < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
MIGRATION = 'DestroyInvalidMembers'
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: MIGRATION,
|
||||
table_name: :members,
|
||||
column_name: :id,
|
||||
job_arguments: []
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# noop
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
933cb5a869696f2343b0b8dfc32f94a64ed7a5119c3f6b2b64ce30e3ae4e555c
|
|
@ -32,7 +32,7 @@ module Banzai
|
|||
# Corresponds to the $$\n...\n$$ syntax
|
||||
DOLLAR_DISPLAY_BLOCK_PATTERN = %r{
|
||||
^(?<matched>\$\$\ *\n(?<math>.*)\n\$\$\ *)$
|
||||
}x.freeze
|
||||
}mx.freeze
|
||||
|
||||
# Order dependent. Handle the `$$` syntax before the `$` syntax
|
||||
DOLLAR_MATH_PIPELINE = [
|
||||
|
|
|
@ -42348,6 +42348,9 @@ msgstr ""
|
|||
msgid "Todos|Assigned"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Could not merge"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Design"
|
||||
msgstr ""
|
||||
|
||||
|
@ -42399,9 +42402,15 @@ msgstr ""
|
|||
msgid "Todos|Pipelines"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Removed from Merge Train:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Review requested"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|The pipeline failed in"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Undo mark all as done"
|
||||
msgstr ""
|
||||
|
||||
|
@ -42414,6 +42423,24 @@ msgstr ""
|
|||
msgid "Todos|Your To-Do List shows what to work on next"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|added a todo for"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|mentioned %{who} on"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|requested a review of"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|set %{who} as an approver for"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|yourself"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todo|at %{todo_parent_path}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle GitLab Next"
|
||||
msgstr ""
|
||||
|
||||
|
@ -45418,6 +45445,12 @@ msgstr ""
|
|||
msgid "Webhooks|Push to the repository."
|
||||
msgstr ""
|
||||
|
||||
msgid "Webhooks|Regex such as %{REGEX_CODE} is supported."
|
||||
msgstr ""
|
||||
|
||||
msgid "Webhooks|Regular expression"
|
||||
msgstr ""
|
||||
|
||||
msgid "Webhooks|Releases events"
|
||||
msgstr ""
|
||||
|
||||
|
@ -45478,6 +45511,12 @@ msgstr ""
|
|||
msgid "Webhooks|Wiki page events"
|
||||
msgstr ""
|
||||
|
||||
msgid "Webhooks|Wildcard pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Webhooks|Wildcards such as %{WILDCARD_CODE_STABLE} or %{WILDCARD_CODE_PRODUCTION} are supported."
|
||||
msgstr ""
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
|
@ -47276,6 +47315,12 @@ msgstr ""
|
|||
msgid "assign yourself"
|
||||
msgstr ""
|
||||
|
||||
msgid "assigned"
|
||||
msgstr ""
|
||||
|
||||
msgid "assigned you"
|
||||
msgstr ""
|
||||
|
||||
msgid "at"
|
||||
msgstr ""
|
||||
|
||||
|
@ -48018,6 +48063,9 @@ msgid_plural "from %d jobs"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "from yourself"
|
||||
msgstr ""
|
||||
|
||||
msgid "frontmatter"
|
||||
msgstr ""
|
||||
|
||||
|
@ -49076,6 +49124,9 @@ msgstr ""
|
|||
msgid "time summary"
|
||||
msgstr ""
|
||||
|
||||
msgid "to yourself"
|
||||
msgstr ""
|
||||
|
||||
msgid "today"
|
||||
msgstr ""
|
||||
|
||||
|
@ -49212,6 +49263,9 @@ msgstr ""
|
|||
msgid "yaml invalid"
|
||||
msgstr ""
|
||||
|
||||
msgid "you"
|
||||
msgstr ""
|
||||
|
||||
msgid "your GitLab instance"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
"codesandbox-api": "0.0.23",
|
||||
"compression-webpack-plugin": "^5.0.2",
|
||||
"copy-webpack-plugin": "^6.4.1",
|
||||
"core-js": "^3.25.5",
|
||||
"core-js": "^3.26.0",
|
||||
"cron-validator": "^1.1.1",
|
||||
"cronstrue": "^1.122.0",
|
||||
"cropper": "^2.3.0",
|
||||
|
|
|
@ -28,9 +28,14 @@ module QA
|
|||
end
|
||||
|
||||
base.view 'app/assets/javascripts/access_tokens/components/new_access_token_app.vue' do
|
||||
element :access_token_section
|
||||
element :created_access_token_field
|
||||
end
|
||||
|
||||
base.view 'app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue' do
|
||||
element :toggle_visibility_button
|
||||
end
|
||||
|
||||
base.view 'app/assets/javascripts/access_tokens/components/access_token_table_app.vue' do
|
||||
element :revoke_button
|
||||
end
|
||||
|
@ -49,7 +54,10 @@ module QA
|
|||
end
|
||||
|
||||
def created_access_token
|
||||
find_element(:created_access_token_field, wait: 30).value
|
||||
within_element(:access_token_section) do
|
||||
click_element(:toggle_visibility_button, wait: 30)
|
||||
find_element(:created_access_token_field).value
|
||||
end
|
||||
end
|
||||
|
||||
def fill_expiry_date(date)
|
||||
|
|
|
@ -1380,7 +1380,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
|||
{
|
||||
'Channel' => {
|
||||
'Subprotocols' => ["terminal.gitlab.com"],
|
||||
'Url' => 'wss://localhost/proxy/build/default_port/',
|
||||
'Url' => 'wss://gitlab.example.com/proxy/build/default_port/',
|
||||
'Header' => {
|
||||
'Authorization' => [nil]
|
||||
},
|
||||
|
@ -1536,7 +1536,8 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
|||
allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil)
|
||||
|
||||
expect(job.runner_session_url).to start_with('https://')
|
||||
expect(Gitlab::Workhorse).to receive(:channel_websocket).with(a_hash_including(url: "wss://localhost/proxy/build/default_port/"))
|
||||
expect(Gitlab::Workhorse).to receive(:channel_websocket)
|
||||
.with(a_hash_including(url: "wss://gitlab.example.com/proxy/build/default_port/"))
|
||||
|
||||
make_request
|
||||
end
|
||||
|
|
|
@ -716,7 +716,7 @@ FactoryBot.define do
|
|||
|
||||
trait :with_runner_session do
|
||||
after(:build) do |build|
|
||||
build.build_runner_session(url: 'https://localhost')
|
||||
build.build_runner_session(url: 'https://gitlab.example.com')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,18 +4,11 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
|
||||
include Spec::Support::Helpers::ModalHelpers
|
||||
include Spec::Support::Helpers::AccessTokenHelpers
|
||||
|
||||
let(:admin) { create(:admin) }
|
||||
let!(:user) { create(:user) }
|
||||
|
||||
def active_impersonation_tokens
|
||||
find("[data-testid='active-tokens']")
|
||||
end
|
||||
|
||||
def created_impersonation_token
|
||||
find_field('new-access-token').value
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(admin)
|
||||
gitlab_enable_admin_mode_sign_in(admin)
|
||||
|
@ -39,12 +32,12 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
|
|||
|
||||
click_on "Create impersonation token"
|
||||
|
||||
expect(active_impersonation_tokens).to have_text(name)
|
||||
expect(active_impersonation_tokens).to have_text('in')
|
||||
expect(active_impersonation_tokens).to have_text('read_api')
|
||||
expect(active_impersonation_tokens).to have_text('read_user')
|
||||
expect(active_access_tokens).to have_text(name)
|
||||
expect(active_access_tokens).to have_text('in')
|
||||
expect(active_access_tokens).to have_text('read_api')
|
||||
expect(active_access_tokens).to have_text('read_user')
|
||||
expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1)
|
||||
expect(created_impersonation_token).not_to be_empty
|
||||
expect(created_access_token).to match(/[\w-]{20}/)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,16 +48,16 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
|
|||
it 'only shows impersonation tokens' do
|
||||
visit admin_user_impersonation_tokens_path(user_id: user.username)
|
||||
|
||||
expect(active_impersonation_tokens).to have_text(impersonation_token.name)
|
||||
expect(active_impersonation_tokens).not_to have_text(personal_access_token.name)
|
||||
expect(active_impersonation_tokens).to have_text('in')
|
||||
expect(active_access_tokens).to have_text(impersonation_token.name)
|
||||
expect(active_access_tokens).not_to have_text(personal_access_token.name)
|
||||
expect(active_access_tokens).to have_text('in')
|
||||
end
|
||||
|
||||
it 'shows absolute times' do
|
||||
admin.update!(time_display_relative: false)
|
||||
visit admin_user_impersonation_tokens_path(user_id: user.username)
|
||||
|
||||
expect(active_impersonation_tokens).to have_text(personal_access_token.expires_at.strftime('%b %-d'))
|
||||
expect(active_access_tokens).to have_text(personal_access_token.expires_at.strftime('%b %-d'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -76,7 +69,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
|
|||
|
||||
accept_gl_confirm(button_text: 'Revoke') { click_on "Revoke" }
|
||||
|
||||
expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.")
|
||||
expect(active_access_tokens).to have_text("This user has no active impersonation tokens.")
|
||||
end
|
||||
|
||||
it "removes expired tokens from 'active' section" do
|
||||
|
@ -84,7 +77,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
|
|||
|
||||
visit admin_user_impersonation_tokens_path(user_id: user.username)
|
||||
|
||||
expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.")
|
||||
expect(active_access_tokens).to have_text("This user has no active impersonation tokens.")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,22 +4,11 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe 'Profile > Personal Access Tokens', :js do
|
||||
include Spec::Support::Helpers::ModalHelpers
|
||||
include Spec::Support::Helpers::AccessTokenHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:pat_create_service) { double('PersonalAccessTokens::CreateService', execute: ServiceResponse.error(message: 'error', payload: { personal_access_token: PersonalAccessToken.new })) }
|
||||
|
||||
def active_personal_access_tokens
|
||||
find("[data-testid='active-tokens']")
|
||||
end
|
||||
|
||||
def created_personal_access_token
|
||||
find_field('new-access-token').value
|
||||
end
|
||||
|
||||
def feed_token_description
|
||||
"Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs."
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
@ -43,11 +32,11 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
|
|||
click_on "Create personal access token"
|
||||
wait_for_all_requests
|
||||
|
||||
expect(active_personal_access_tokens).to have_text(name)
|
||||
expect(active_personal_access_tokens).to have_text('in')
|
||||
expect(active_personal_access_tokens).to have_text('read_api')
|
||||
expect(active_personal_access_tokens).to have_text('read_user')
|
||||
expect(created_personal_access_token).not_to be_empty
|
||||
expect(active_access_tokens).to have_text(name)
|
||||
expect(active_access_tokens).to have_text('in')
|
||||
expect(active_access_tokens).to have_text('read_api')
|
||||
expect(active_access_tokens).to have_text('read_user')
|
||||
expect(created_access_token).to match(/[\w-]{20}/)
|
||||
end
|
||||
|
||||
context "when creation fails" do
|
||||
|
@ -73,8 +62,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
|
|||
it 'only shows personal access tokens' do
|
||||
visit profile_personal_access_tokens_path
|
||||
|
||||
expect(active_personal_access_tokens).to have_text(personal_access_token.name)
|
||||
expect(active_personal_access_tokens).not_to have_text(impersonation_token.name)
|
||||
expect(active_access_tokens).to have_text(personal_access_token.name)
|
||||
expect(active_access_tokens).not_to have_text(impersonation_token.name)
|
||||
end
|
||||
|
||||
context 'when User#time_display_relative is false' do
|
||||
|
@ -85,7 +74,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
|
|||
it 'shows absolute times for expires_at' do
|
||||
visit profile_personal_access_tokens_path
|
||||
|
||||
expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.expires_at.strftime('%b %-d'))
|
||||
expect(active_access_tokens).to have_text(PersonalAccessToken.last.expires_at.strftime('%b %-d'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -97,14 +86,14 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
|
|||
visit profile_personal_access_tokens_path
|
||||
accept_gl_confirm(button_text: 'Revoke') { click_on "Revoke" }
|
||||
|
||||
expect(active_personal_access_tokens).to have_text("This user has no active personal access tokens.")
|
||||
expect(active_access_tokens).to have_text("This user has no active personal access tokens.")
|
||||
end
|
||||
|
||||
it "removes expired tokens from 'active' section" do
|
||||
personal_access_token.update!(expires_at: 5.days.ago)
|
||||
visit profile_personal_access_tokens_path
|
||||
|
||||
expect(active_personal_access_tokens).to have_text("This user has no active personal access tokens.")
|
||||
expect(active_access_tokens).to have_text("This user has no active personal access tokens.")
|
||||
end
|
||||
|
||||
context "when revocation fails" do
|
||||
|
@ -115,12 +104,16 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
|
|||
visit profile_personal_access_tokens_path
|
||||
|
||||
accept_gl_confirm(button_text: "Revoke") { click_on "Revoke" }
|
||||
expect(active_personal_access_tokens).to have_text(personal_access_token.name)
|
||||
expect(active_access_tokens).to have_text(personal_access_token.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "feed token" do
|
||||
def feed_token_description
|
||||
"Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs."
|
||||
end
|
||||
|
||||
context "when enabled" do
|
||||
it "displays feed token" do
|
||||
allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false)
|
||||
|
|
|
@ -87,7 +87,7 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do
|
|||
expect(page).to have_content('SSL Verification: enabled')
|
||||
expect(page).to have_content('Tag push events')
|
||||
expect(page).to have_content('Job events')
|
||||
expect(page).to have_selector('.js-vue-push-events', visible: :all)
|
||||
expect(page).to have_content('Push events')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@ describe('~/access_tokens/components/new_access_token_app', () => {
|
|||
expect(InputCopyToggleVisibilityComponent.props('copyButtonTitle')).toBe(
|
||||
sprintf(__('Copy %{accessTokenType}'), { accessTokenType }),
|
||||
);
|
||||
expect(InputCopyToggleVisibilityComponent.props('initialVisibility')).toBe(true);
|
||||
expect(InputCopyToggleVisibilityComponent.attributes('label')).toBe(
|
||||
sprintf(__('Your new %{accessTokenType}'), { accessTokenType }),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing existing hook with "all_branches" strategy selected 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="all_branches"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing existing hook with "regex" strategy selected 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="regex"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<gl-form-input-stub
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
name="hook[push_events_branch_filter]"
|
||||
value="foo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="form-text text-muted custom-control"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Regex such as %{REGEX_CODE} is supported."
|
||||
/>
|
||||
</p>
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing existing hook with "wildcard" strategy selected 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="wildcard"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<gl-form-input-stub
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
name="hook[push_events_branch_filter]"
|
||||
value="foo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="form-text text-muted custom-control"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Wildcards such as %{WILDCARD_CODE_STABLE} or %{WILDCARD_CODE_PRODUCTION} are supported."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing new hook all_branches should be selected by default 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="all_branches"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing new hook should be able to set regex rule 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="regex"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<gl-form-input-stub
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
name="hook[push_events_branch_filter]"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="form-text text-muted custom-control"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Regex such as %{REGEX_CODE} is supported."
|
||||
/>
|
||||
</p>
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
||||
|
||||
exports[`Webhook push events form editor component Different push events rules when editing new hook should be able to set wildcard rule 1`] = `
|
||||
<gl-form-radio-group-stub
|
||||
checked="wildcard"
|
||||
disabledfield="disabled"
|
||||
htmlfield="html"
|
||||
name="hook[branch_filter_strategy]"
|
||||
options=""
|
||||
textfield="text"
|
||||
valuefield="value"
|
||||
>
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_all_branches"
|
||||
value="all_branches"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_all"
|
||||
>
|
||||
All branches
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_wildcard"
|
||||
value="wildcard"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_wildcard"
|
||||
>
|
||||
|
||||
Wildcard pattern
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<gl-form-input-stub
|
||||
data-qa-selector="webhook_branch_filter_field"
|
||||
data-testid="webhook_branch_filter_field"
|
||||
name="hook[push_events_branch_filter]"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="form-text text-muted custom-control"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Wildcards such as %{WILDCARD_CODE_STABLE} or %{WILDCARD_CODE_PRODUCTION} are supported."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<gl-form-radio-stub
|
||||
class="gl-mt-2 branch-filter-strategy-radio"
|
||||
data-testid="rule_regex"
|
||||
value="regex"
|
||||
>
|
||||
<div
|
||||
data-qa-selector="strategy_radio_regex"
|
||||
>
|
||||
|
||||
Regular expression
|
||||
|
||||
</div>
|
||||
</gl-form-radio-stub>
|
||||
|
||||
<div
|
||||
class="gl-ml-6"
|
||||
>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</gl-form-radio-group-stub>
|
||||
`;
|
|
@ -0,0 +1,117 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { GlFormCheckbox, GlFormRadioGroup } from '@gitlab/ui';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import PushEvents from '~/webhooks/components/push_events.vue';
|
||||
|
||||
describe('Webhook push events form editor component', () => {
|
||||
let wrapper;
|
||||
|
||||
const findPushEventsCheckBox = (w = wrapper) => w.findComponent(GlFormCheckbox);
|
||||
const findPushEventsIndicator = (w = wrapper) => w.find('input[name="hook[push_events]"]');
|
||||
const findPushEventRulesGroup = (w = wrapper) => w.findComponent(GlFormRadioGroup);
|
||||
const getPushEventsRuleValue = (w = wrapper) => findPushEventRulesGroup(w).vm.$attrs.checked;
|
||||
const findWildcardRuleInput = (w = wrapper) => w.findByTestId('webhook_branch_filter_field');
|
||||
const findRegexRuleInput = (w = wrapper) => w.findByTestId('webhook_branch_filter_field');
|
||||
|
||||
const createComponent = (provides) =>
|
||||
shallowMountExtended(PushEvents, {
|
||||
provide: {
|
||||
isNewHook: true,
|
||||
pushEvents: false,
|
||||
strategy: 'wildcard',
|
||||
pushEventsBranchFilter: '',
|
||||
...provides,
|
||||
},
|
||||
});
|
||||
|
||||
describe('Renders push events checkbox', () => {
|
||||
it('when it is a new hook', async () => {
|
||||
wrapper = createComponent({
|
||||
isNewHook: true,
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
const checkbox = findPushEventsCheckBox();
|
||||
expect(checkbox.exists()).toBe(true);
|
||||
expect(findPushEventRulesGroup().exists()).toBe(false);
|
||||
expect(findPushEventsIndicator().attributes('value')).toBe('false');
|
||||
});
|
||||
|
||||
it('when it is not a new hook and push events is enabled', async () => {
|
||||
wrapper = createComponent({
|
||||
isNewHook: false,
|
||||
pushEvents: true,
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
expect(findPushEventsCheckBox().exists()).toBe(true);
|
||||
expect(findPushEventRulesGroup().exists()).toBe(true);
|
||||
expect(findPushEventsIndicator().attributes('value')).toBe('true');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Different push events rules', () => {
|
||||
describe('when editing new hook', () => {
|
||||
beforeEach(async () => {
|
||||
wrapper = createComponent({
|
||||
isNewHook: true,
|
||||
});
|
||||
await nextTick();
|
||||
await findPushEventsCheckBox().vm.$emit('input', true);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('all_branches should be selected by default', async () => {
|
||||
expect(findPushEventRulesGroup().element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be able to set wildcard rule', async () => {
|
||||
expect(getPushEventsRuleValue()).toBe('all_branches');
|
||||
expect(findWildcardRuleInput().exists()).toBe(false);
|
||||
expect(findRegexRuleInput().exists()).toBe(false);
|
||||
|
||||
await findPushEventRulesGroup(wrapper).vm.$emit('input', 'wildcard');
|
||||
expect(findWildcardRuleInput().exists()).toBe(true);
|
||||
expect(findPushEventRulesGroup().element).toMatchSnapshot();
|
||||
|
||||
const testVal = 'test-val';
|
||||
findWildcardRuleInput().vm.$emit('input', testVal);
|
||||
await nextTick();
|
||||
expect(findWildcardRuleInput().attributes('value')).toBe(testVal);
|
||||
});
|
||||
|
||||
it('should be able to set regex rule', async () => {
|
||||
expect(getPushEventsRuleValue()).toBe('all_branches');
|
||||
expect(findRegexRuleInput().exists()).toBe(false);
|
||||
expect(findWildcardRuleInput().exists()).toBe(false);
|
||||
|
||||
await findPushEventRulesGroup(wrapper).vm.$emit('input', 'regex');
|
||||
expect(findRegexRuleInput().exists()).toBe(true);
|
||||
expect(findPushEventRulesGroup().element).toMatchSnapshot();
|
||||
|
||||
const testVal = 'test-val';
|
||||
findRegexRuleInput().vm.$emit('input', testVal);
|
||||
await nextTick();
|
||||
expect(findRegexRuleInput().attributes('value')).toBe(testVal);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when editing existing hook', () => {
|
||||
it.each(['all_branches', 'wildcard', 'regex'])(
|
||||
'with "%s" strategy selected',
|
||||
async (strategy) => {
|
||||
wrapper = createComponent({
|
||||
isNewHook: false,
|
||||
pushEvents: true,
|
||||
pushEventsBranchFilter: 'foo',
|
||||
strategy,
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
expect(findPushEventsIndicator().attributes('value')).toBe('true');
|
||||
expect(findPushEventRulesGroup().element).toMatchSnapshot();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,6 +4,30 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe EventsHelper do
|
||||
include Gitlab::Routing
|
||||
include Banzai::Filter::OutputSafety
|
||||
|
||||
describe '#link_to_author' do
|
||||
let(:user) { create(:user) }
|
||||
let(:event) { create(:event, author: user) }
|
||||
|
||||
it 'returns a link to the author' do
|
||||
name = user.name
|
||||
expect(helper.link_to_author(event)).to eq(link_to(name, user_path(user.username), title: name))
|
||||
end
|
||||
|
||||
it 'returns the author name if the author is not present' do
|
||||
event.author = nil
|
||||
|
||||
expect(helper.link_to_author(event)).to eq(escape_once(event.author_name))
|
||||
end
|
||||
|
||||
it 'returns "You" if the author is the current user' do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
|
||||
name = _('You')
|
||||
expect(helper.link_to_author(event, self_added: true)).to eq(link_to(name, user_path(user.username), title: name))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#event_target_path' do
|
||||
subject { helper.event_target_path(event.present) }
|
||||
|
|
|
@ -150,4 +150,54 @@ RSpec.describe IntegrationsHelper do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#integration_issue_type' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
let_it_be(:issue) { create(:issue) }
|
||||
|
||||
where(:issue_type, :expected_i18n_issue_type) do
|
||||
"issue" | _('Issue')
|
||||
"incident" | _('Incident')
|
||||
"test_case" | _('Test case')
|
||||
"requirement" | _('Requirement')
|
||||
"task" | _('Task')
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
issue.update!(issue_type: issue_type)
|
||||
end
|
||||
|
||||
it "return the correct i18n issue type" do
|
||||
expect(described_class.integration_issue_type(issue.issue_type)).to eq(expected_i18n_issue_type)
|
||||
end
|
||||
end
|
||||
|
||||
it "only consider these enumeration values are valid" do
|
||||
expected_valid_types = %w[issue incident test_case requirement task]
|
||||
expect(Issue.issue_types.keys).to contain_exactly(*expected_valid_types)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#integration_todo_target_type' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
let!(:todo) { create(:todo, commit_id: '123') }
|
||||
|
||||
where(:target_type, :expected_i18n_target_type) do
|
||||
"Commit" | _("Commit")
|
||||
"Issue" | _("Issue")
|
||||
"MergeRequest" | _("Merge Request")
|
||||
'Epic' | _('Epic')
|
||||
DesignManagement::Design.name | _('design')
|
||||
AlertManagement::Alert.name | _('alert')
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
todo.update!(target_type: target_type)
|
||||
end
|
||||
|
||||
it { expect(described_class.integration_todo_target_type(todo.target_type)).to eq(expected_i18n_target_type) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -310,4 +310,33 @@ RSpec.describe TodosHelper do
|
|||
it { expect(helper.todos_filter_params[:state]).to eq(result) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#todo_action_name' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:action, :self_added?, :expected_action_name) do
|
||||
Todo::ASSIGNED | false | s_('Todos|assigned you')
|
||||
Todo::ASSIGNED | true | s_('Todos|assigned')
|
||||
Todo::REVIEW_REQUESTED | true | s_('Todos|requested a review of')
|
||||
Todo::MENTIONED | true | format(s_("Todos|mentioned %{who} on"), who: s_('Todos|yourself'))
|
||||
Todo::MENTIONED | false | format(s_("Todos|mentioned %{who} on"), who: _('you'))
|
||||
Todo::DIRECTLY_ADDRESSED | true | format(s_("Todos|mentioned %{who} on"), who: s_('Todos|yourself'))
|
||||
Todo::DIRECTLY_ADDRESSED | false | format(s_("Todos|mentioned %{who} on"), who: _('you'))
|
||||
Todo::BUILD_FAILED | true | s_('Todos|The pipeline failed in')
|
||||
Todo::MARKED | true | s_('Todos|added a todo for')
|
||||
Todo::APPROVAL_REQUIRED | true | format(s_("Todos|set %{who} as an approver for"), who: s_('Todos|yourself'))
|
||||
Todo::APPROVAL_REQUIRED | false | format(s_("Todos|set %{who} as an approver for"), who: _('you'))
|
||||
Todo::UNMERGEABLE | true | s_('Todos|Could not merge')
|
||||
Todo::MERGE_TRAIN_REMOVED | true | s_("Todos|Removed from Merge Train:")
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
alert_todo.action = action
|
||||
alert_todo.user = self_added? ? alert_todo.author : user
|
||||
end
|
||||
|
||||
it { expect(helper.todo_action_name(alert_todo)).to eq(expected_action_name) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -97,7 +97,8 @@ RSpec.describe Banzai::Filter::MathFilter do
|
|||
describe 'block display math using $$\n...\n$$ syntax' do
|
||||
context 'with valid syntax' do
|
||||
where(:text, :result_template) do
|
||||
"$$\n2+2\n$$" | "<math>2+2</math>"
|
||||
"$$\n2+2\n$$" | "<math>2+2</math>"
|
||||
"$$\n2+2\n3+4\n$$" | "<math>2+2\n3+4</math>"
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe FinalizeInvalidMemberCleanup, :migration do
|
||||
let(:batched_migrations) { table(:batched_background_migrations) }
|
||||
|
||||
let_it_be(:migration) { described_class::MIGRATION }
|
||||
|
||||
describe '#up' do
|
||||
shared_examples 'finalizes the migration' do
|
||||
it 'finalizes the migration' do
|
||||
allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner|
|
||||
expect(runner).to receive(:finalize).with('DestroyInvalidMembers', :members, :id, [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when migration is missing' do
|
||||
it 'warns migration not found' do
|
||||
expect(Gitlab::AppLogger)
|
||||
.to receive(:warn).with(/Could not find batched background migration for the given configuration:/)
|
||||
|
||||
migrate!
|
||||
end
|
||||
end
|
||||
|
||||
context 'with migration present' do
|
||||
let!(:destroy_invalid_member_migration) do
|
||||
batched_migrations.create!(
|
||||
job_class_name: 'DestroyInvalidMembers',
|
||||
table_name: :members,
|
||||
column_name: :id,
|
||||
job_arguments: [],
|
||||
interval: 2.minutes,
|
||||
min_value: 1,
|
||||
max_value: 2,
|
||||
batch_size: 1000,
|
||||
sub_batch_size: 200,
|
||||
gitlab_schema: :gitlab_main,
|
||||
status: 3 # finished
|
||||
)
|
||||
end
|
||||
|
||||
context 'when migration finished successfully' do
|
||||
it 'does not raise exception' do
|
||||
expect { migrate! }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'with different migration statuses' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:status, :description) do
|
||||
0 | 'paused'
|
||||
1 | 'active'
|
||||
4 | 'failed'
|
||||
5 | 'finalizing'
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
destroy_invalid_member_migration.update!(status: status)
|
||||
end
|
||||
|
||||
it_behaves_like 'finalizes the migration'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -72,7 +72,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
let(:specification) { subject.service_specification(service: service, port: port, path: path, subprotocols: subprotocols) }
|
||||
|
||||
it 'returns service proxy url' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/#{service}/#{port}/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/#{service}/#{port}/#{path}"
|
||||
end
|
||||
|
||||
it 'returns default service proxy websocket subprotocol' do
|
||||
|
@ -89,7 +89,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
let(:port) { nil }
|
||||
|
||||
it 'uses the default port name' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/#{service}/default_port/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/#{service}/default_port/#{path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -97,7 +97,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
let(:service) { '' }
|
||||
|
||||
it 'uses the service name "build" as default' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/build/#{port}/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/build/#{port}/#{path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
module Spec
|
||||
module Support
|
||||
module Helpers
|
||||
module AccessTokenHelpers
|
||||
def active_access_tokens
|
||||
find("[data-testid='active-tokens']")
|
||||
end
|
||||
|
||||
def created_access_token
|
||||
within('[data-testid=access-token-section]') do
|
||||
find('[data-testid=toggle-visibility-button]').click
|
||||
find_field('new-access-token').value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,13 +9,7 @@ RSpec.shared_examples 'resource access tokens missing access rights' do
|
|||
end
|
||||
|
||||
RSpec.shared_examples 'resource access tokens creation' do |resource_type|
|
||||
def active_resource_access_tokens
|
||||
find("[data-testid='active-tokens']")
|
||||
end
|
||||
|
||||
def created_resource_access_token
|
||||
find_field('new-access-token').value
|
||||
end
|
||||
include Spec::Support::Helpers::AccessTokenHelpers
|
||||
|
||||
it 'allows creation of an access token', :aggregate_failures do
|
||||
name = 'My access token'
|
||||
|
@ -34,12 +28,12 @@ RSpec.shared_examples 'resource access tokens creation' do |resource_type|
|
|||
|
||||
click_on "Create #{resource_type} access token"
|
||||
|
||||
expect(active_resource_access_tokens).to have_text(name)
|
||||
expect(active_resource_access_tokens).to have_text('in')
|
||||
expect(active_resource_access_tokens).to have_text('read_api')
|
||||
expect(active_resource_access_tokens).to have_text('read_repository')
|
||||
expect(active_resource_access_tokens).to have_text('Guest')
|
||||
expect(created_resource_access_token).not_to be_empty
|
||||
expect(active_access_tokens).to have_text(name)
|
||||
expect(active_access_tokens).to have_text('in')
|
||||
expect(active_access_tokens).to have_text('read_api')
|
||||
expect(active_access_tokens).to have_text('read_repository')
|
||||
expect(active_access_tokens).to have_text('Guest')
|
||||
expect(created_access_token).to match(/[\w-]{20}/)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/smartystreets/goconvey v1.7.2
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
gitlab.com/gitlab-org/gitaly/v15 v15.4.2
|
||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
|
||||
gitlab.com/gitlab-org/labkit v1.16.0
|
||||
|
|
|
@ -896,8 +896,9 @@ github.com/ssgelm/cookiejarparser v1.0.1/go.mod h1:DUfC0mpjIzlDN7DzKjXpHj0qMI5m9
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
@ -906,8 +907,9 @@ github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
|
||||
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
|
|
|
@ -3903,10 +3903,10 @@ core-js-pure@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
|
||||
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
|
||||
|
||||
core-js@^3.25.5:
|
||||
version "3.25.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
|
||||
integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
|
||||
core-js@^3.26.0:
|
||||
version "3.26.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.0.tgz#a516db0ed0811be10eac5d94f3b8463d03faccfe"
|
||||
integrity sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
|
|
Loading…
Reference in New Issue