Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-09 18:08:13 +00:00
parent d2675fa4de
commit f8b0e661f8
30 changed files with 503 additions and 82 deletions

View File

@ -52,7 +52,6 @@ qa:nightly-auto-quarantine-dequarantine:
- bundle exec confiner -r .confiner/nightly.yml
allow_failure: true
qa:selectors-as-if-foss:
extends:
- qa:selectors
@ -68,6 +67,30 @@ update-qa-cache:
script:
- echo "Cache has been updated and ready to be uploaded."
populate-qa-tests-var:
extends:
- .qa:rules:package-and-qa
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: prepare
script:
- tooling/bin/qa/check_if_qa_only_spec_changes ${CHANGES_FILE} ${ONLY_QA_CHANGES_FILE}
- '[ -f $ONLY_QA_CHANGES_FILE ] && export QA_TESTS="`cat $ONLY_QA_CHANGES_FILE`"'
- 'echo "QA_TESTS=$QA_TESTS" >> qa_tests_var.env'
- 'echo "QA_TESTS: $QA_TESTS"'
artifacts:
expire_in: 2d
reports:
dotenv: qa_tests_var.env
paths:
- ${CHANGES_FILE}
- ${ONLY_QA_CHANGES_FILE}
- qa_tests_var.env
variables:
CHANGES_FILE: tmp/changed_files.txt
ONLY_QA_CHANGES_FILE: tmp/qa_only_changed_files.txt
needs:
- detect-tests
.package-and-qa-base:
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: qa
@ -77,8 +100,6 @@ update-qa-cache:
- install_gitlab_gem
- tooling/bin/find_change_diffs ${CHANGES_DIFFS_DIR}
script:
- tooling/bin/qa/check_if_qa_only_spec_changes ${CHANGES_FILE} ${ONLY_QA_CHANGES_FILE}
- '[ -f $ONLY_QA_CHANGES_FILE ] && export QA_TESTS="`cat $ONLY_QA_CHANGES_FILE`"'
- 'echo "QA_TESTS: $QA_TESTS"'
- exit_code=0 && tooling/bin/qa/package_and_qa_check ${CHANGES_DIFFS_DIR} || exit_code=$?
- echo $exit_code
@ -99,16 +120,13 @@ update-qa-cache:
artifacts: false
- job: build-assets-image
artifacts: false
- job: populate-qa-tests-var
- detect-tests
artifacts:
expire_in: 7d
paths:
- ${CHANGES_FILE}
- ${ONLY_QA_CHANGES_FILE}
- ${CHANGES_DIFFS_DIR}/*
variables:
CHANGES_FILE: tmp/changed_files.txt
ONLY_QA_CHANGES_FILE: tmp/qa_only_changed_files.txt
CHANGES_DIFFS_DIR: tmp/diffs
ALLURE_JOB_NAME: $CI_JOB_NAME

View File

@ -23,8 +23,7 @@ import JobItem from './job_item.vue';
export default {
i18n: {
stage: __('Stage:'),
loadingTextLineOne: __('Loading, please wait.'),
loadingTextLineTwo: __('Cue dramatic background music...'),
loadingText: __('Loading, please wait.'),
},
dropdownPopperOpts: {
placement: 'bottom',
@ -138,14 +137,11 @@ export default {
</template>
<div
v-if="isLoading"
class="gl-display-flex gl-justify-content-center gl-p-3"
class="gl-display-flex gl-justify-content-center gl-p-2"
data-testid="pipeline-stage-loading-state"
>
<gl-loading-icon size="sm" class="gl-mr-3" />
<div>
<p class="gl-mb-0">{{ $options.i18n.loadingTextLineOne }}</p>
<p class="gl-mb-0">{{ $options.i18n.loadingTextLineTwo }}</p>
</div>
<p class="gl-mb-0">{{ $options.i18n.loadingText }}</p>
</div>
<ul
v-else

View File

@ -104,7 +104,7 @@ export default {
@selectRevision="onSelectRevision"
/>
<div
class="compare-ellipsis gl-display-flex gl-justify-content-center gl-align-items-center gl-my-4 gl-md-my-0"
class="compare-ellipsis gl-display-flex gl-justify-content-center gl-align-items-center gl-align-self-end gl-my-4 gl-md-my-0"
data-testid="ellipsis"
>
...
@ -121,7 +121,7 @@ export default {
@selectRevision="onSelectRevision"
/>
</div>
<div class="gl-mt-4">
<div class="gl-mt-6">
<gl-button category="primary" variant="confirm" @click="onSubmit">
{{ s__('CompareRevisions|Compare') }}
</gl-button>

View File

@ -1,5 +1,4 @@
<script>
import { GlCard } from '@gitlab/ui';
import RepoDropdown from './repo_dropdown.vue';
import RevisionDropdown from './revision_dropdown.vue';
@ -7,7 +6,6 @@ export default {
components: {
RepoDropdown,
RevisionDropdown,
GlCard,
},
props: {
refsProjectPath: {
@ -41,10 +39,10 @@ export default {
</script>
<template>
<gl-card header-class="gl-py-2 gl-px-3 gl-font-weight-bold" body-class="gl-px-3">
<template #header>
<div class="revision-card gl-flex-basis-half">
<h2 class="gl-font-size-h2">
{{ s__(`CompareRevisions|${revisionText}`) }}
</template>
</h2>
<div class="gl-sm-display-flex gl-align-items-center">
<repo-dropdown
class="gl-sm-w-half"
@ -61,5 +59,5 @@ export default {
v-on="$listeners"
/>
</div>
</gl-card>
</div>
</template>

View File

@ -1,11 +1,5 @@
<script>
import {
GlFormGroup,
GlDropdown,
GlDropdownForm,
GlDropdownItem,
GlDropdownDivider,
} from '@gitlab/ui';
import { GlDropdown, GlDropdownForm, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
import { s__ } from '~/locale';
import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
@ -17,10 +11,8 @@ export default {
showInstallationInstructions: s__(
'Runners|Show runner installation and registration instructions',
),
registrationToken: s__('Runners|Registration token'),
},
components: {
GlFormGroup,
GlDropdown,
GlDropdownForm,
GlDropdownItem,
@ -92,9 +84,7 @@ export default {
</gl-dropdown-item>
<gl-dropdown-divider />
<gl-dropdown-form class="gl-p-4!">
<gl-form-group class="gl-mb-0" :label="$options.i18n.registrationToken">
<registration-token :value="currentRegistrationToken" />
</gl-form-group>
<registration-token input-id="token-value" :value="currentRegistrationToken" />
</gl-dropdown-form>
<gl-dropdown-divider />
<registration-token-reset-dropdown-item :type="type" @tokenReset="onTokenReset" />

View File

@ -6,7 +6,14 @@ export default {
components: {
InputCopyToggleVisibility,
},
i18n: {
registrationToken: s__('Runners|Registration token'),
},
props: {
inputId: {
type: String,
required: true,
},
value: {
type: String,
required: false,
@ -16,7 +23,7 @@ export default {
computed: {
formInputGroupProps() {
return {
name: 'token-value',
id: this.inputId,
};
},
},
@ -33,6 +40,8 @@ export default {
<input-copy-toggle-visibility
class="gl-m-0"
:value="value"
:label="$options.i18n.registrationToken"
:label-for="inputId"
:copy-button-title="$options.I18N_COPY_BUTTON_TITLE"
:form-input-group-props="formInputGroupProps"
@copy="onCopy"

View File

@ -2,10 +2,6 @@
import { GlButton, GlTable } from '@gitlab/ui';
import { __, s__ } from '~/locale';
const defaultTableClasses = {
thClass: 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!',
};
export default {
i18n: {
emptyText: s__('CI/CD|No projects have been added to the scope'),
@ -15,14 +11,12 @@ export default {
key: 'project',
label: __('Projects that can be accessed'),
tdClass: 'gl-p-5!',
...defaultTableClasses,
columnClass: 'gl-w-85p',
},
{
key: 'actions',
label: '',
tdClass: 'gl-p-5! gl-text-right',
...defaultTableClasses,
columnClass: 'gl-w-15p',
},
],

View File

@ -0,0 +1,8 @@
= content_tag tag, {**@button_options, **base_attributes, class: button_class, href: @href, target: @target } do
- if @loading
= gl_loading_icon(inline: true, css_class: 'gl-button-icon gl-button-loading-indicator')
- if @icon && (!@loading || content)
= sprite_icon(@icon, css_class: "gl-icon gl-button-icon #{@icon_classes}")
- if content
%span.gl-button-text{ class: @button_text_classes }
= content

View File

@ -0,0 +1,114 @@
# frozen_string_literal: true
module Pajamas
class ButtonComponent < Pajamas::Component
# @param [Symbol] category
# @param [Symbol] variant
# @param [Symbol] size
# @param [Boolean] disabled
# @param [Boolean] loading
# @param [Boolean] block
# @param [Boolean] selected
# @param [String] icon
# @param [String] href
# @param [String] target
# @param [Hash] button_options
# @param [String] button_text_classes
# @param [String] icon_classes
def initialize(
category: :primary,
variant: :default,
size: :medium,
disabled: false,
loading: false,
block: false,
selected: false,
icon: nil,
href: nil,
target: nil,
button_options: {},
button_text_classes: nil,
icon_classes: nil
)
@category = filter_attribute(category.to_sym, CATEGORY_OPTIONS)
@variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS)
@size = filter_attribute(size.to_sym, SIZE_OPTIONS)
@disabled = disabled
@loading = loading
@block = block
@selected = selected
@icon = icon
@href = href
@target = filter_attribute(target, TARGET_OPTIONS)
@button_options = button_options
@button_text_classes = button_text_classes
@icon_classes = icon_classes
end
private
def button_class
classes = ['gl-button btn']
classes.push('disabled') if @disabled || @loading
classes.push('selected') if @selected
classes.push('btn-block') if @block
classes.push('btn-icon') if @icon && !content
classes.push(SIZE_CLASSES[@size])
classes.push(VARIANT_CLASSES[@variant])
unless NON_CATEGORY_VARIANTS.include?(@variant) || @category == :primary
classes.push(VARIANT_CLASSES[@variant] + '-' + CATEGORY_CLASSES[@category])
end
classes.push(@button_options[:class])
classes.join(' ')
end
CATEGORY_OPTIONS = [:primary, :secondary, :tertiary].freeze
VARIANT_OPTIONS = [:default, :confirm, :danger, :dashed, :link, :reset].freeze
SIZE_OPTIONS = [:small, :medium].freeze
TARGET_OPTIONS = %w[_self _blank _parent _top].freeze
CATEGORY_CLASSES = {
primary: '',
secondary: 'secondary',
tertiary: 'tertiary'
}.freeze
VARIANT_CLASSES = {
default: 'btn-default',
confirm: 'btn-confirm',
danger: 'btn-danger',
dashed: 'btn-dashed',
link: 'btn-link',
reset: 'btn-gl-reset'
}.freeze
NON_CATEGORY_VARIANTS = [:dashed, :link, :reset].freeze
SIZE_CLASSES = {
small: 'btn-sm',
medium: 'btn-md'
}.freeze
delegate :sprite_icon, to: :helpers
delegate :gl_loading_icon, to: :helpers
def tag
@href ? 'a' : 'button'
end
def base_attributes
attributes = {}
attributes['disabled'] = '' if @disabled || @loading
attributes['aria-disabled'] = true if @disabled || @loading
attributes['type'] = 'button' unless @href
attributes
end
end
end

View File

@ -90,6 +90,7 @@ class User < ApplicationRecord
include ForcedEmailConfirmation
MINIMUM_INACTIVE_DAYS = 90
MINIMUM_DAYS_CREATED = 7
# Override Devise::Models::Trackable#update_tracked_fields!
# to limit database writes to at most once every hour
@ -479,7 +480,7 @@ class User < ApplicationRecord
scope :order_oldest_last_activity, -> { reorder(arel_table[:last_activity_on].asc.nulls_first) }
scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
scope :dormant, -> { with_state(:active).human_or_service_user.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil) }
scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil).where('created_at <= ?', MINIMUM_DAYS_CREATED.day.ago.to_date) }
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
scope :by_ids_or_usernames, -> (ids, usernames) { where(username: usernames).or(where(id: ids)) }
scope :without_forbidden_states, -> { where.not(state: FORBIDDEN_SEARCH_STATES) }

View File

@ -6,7 +6,7 @@
.settings-header
%h4
= _('Visibility and access controls')
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set default and restrict visibility levels. Configure import sources and git access protocol.')
@ -118,4 +118,4 @@
= render 'admin/application_settings/eks'
= render 'admin/application_settings/floc'
= render_if_exists 'admin/application_settings/add_license'
= render 'admin/application_settings/jira_connect_application_key' if Feature.enabled?(:jira_connect_oauth)
= render 'admin/application_settings/jira_connect_application_key' if Feature.enabled?(:jira_connect_oauth, current_user)

View File

@ -3,7 +3,7 @@
%h1.page-title.gl-font-size-h-display
= _("Compare Git revisions")
.sub-header-block
%div
- example_branch = capture do
%code.ref-name= @project.default_branch_or_main
- example_sha = capture do

View File

@ -17,7 +17,7 @@
paginate_diffs: true,
paginate_diffs_per_page: Projects::CompareController::COMMIT_DIFFS_PER_PAGE
- else
.card.bg-light
.card.gl-bg-gray-50.gl-border-none.gl-p-2
.center
%h4
= s_("CompareBranches|There isn't anything to compare.")

View File

@ -13,8 +13,11 @@
- else
= yield
- if dismissable && !preview
%button.btn.gl-close-btn-color-inherit.gl-broadcast-message-dismiss.btn-default.btn-sm.gl-button.btn-default-tertiary.btn-icon.js-dismiss-current-broadcast-notification{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id, expire_date: message.ends_at.iso8601 } }
= sprite_icon('close', size: 16, css_class: "gl-icon gl-mx-3! gl-text-white")
= render Pajamas::ButtonComponent.new(category: :tertiary,
icon: 'close',
size: :small,
button_options: { class: 'gl-close-btn-color-inherit gl-broadcast-message-dismiss js-dismiss-current-broadcast-notification', 'aria-label': _('Close'), data: { id: message.id, expire_date: message.ends_at.iso8601 } },
icon_classes: 'gl-mx-3! gl-text-white')
- else
- notification_class = "js-broadcast-notification-#{message.id}"
- notification_class << ' preview' if preview
@ -25,5 +28,8 @@
- else
= yield
- if !preview
%button.js-dismiss-current-broadcast-notification.btn.btn-link.gl-button{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id, expire_date: message.ends_at.iso8601 } }
= sprite_icon('close', size: 16, css_class: "gl-icon gl-mx-3! gl-text-gray-700")
= render Pajamas::ButtonComponent.new(variant: :link,
icon: 'close',
size: :small,
button_options: { class: 'js-dismiss-current-broadcast-notification', 'aria-label': _('Close'), data: { id: message.id, expire_date: message.ends_at.iso8601 } },
icon_classes: 'gl-mx-3! gl-text-gray-700')

View File

@ -400,7 +400,7 @@ module Gitlab
resource oauth_path,
headers: %w(Authorization),
credentials: false,
methods: %i(post)
methods: %i(post options)
end
end
@ -411,7 +411,7 @@ module Gitlab
resource '/oauth/userinfo',
headers: %w(Authorization),
credentials: false,
methods: %i(get head post)
methods: %i(get head post options)
end
%w(/oauth/discovery/keys /.well-known/openid-configuration /.well-known/webfinger).each do |openid_path|

View File

@ -14659,7 +14659,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerability finding. |
| <a id="pipelinesecurityreportfindinglinks"></a>`links` | [`[VulnerabilityLink!]`](#vulnerabilitylink) | List of links associated with the vulnerability. |
| <a id="pipelinesecurityreportfindinglocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. |
| <a id="pipelinesecurityreportfindingname"></a>`name` | [`String`](#string) | Name of the vulnerability finding. |
| <a id="pipelinesecurityreportfindingname"></a>`name` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.1. Use `title`. |
| <a id="pipelinesecurityreportfindingproject"></a>`project` | [`Project`](#project) | Project on which the vulnerability finding was found. |
| <a id="pipelinesecurityreportfindingprojectfingerprint"></a>`projectFingerprint` | [`String`](#string) | Name of the vulnerability finding. |
| <a id="pipelinesecurityreportfindingreporttype"></a>`reportType` | [`VulnerabilityReportType`](#vulnerabilityreporttype) | Type of the security report that found the vulnerability finding. |

View File

@ -246,7 +246,7 @@ page](https://go.dev/dl).
# Remove former Go installation folder
sudo rm -rf /usr/local/go
curl --remote-name --location --progress-bar "https://go.dev/dl/go1.17.10.linux-amd64.tar.gz""
curl --remote-name --location --progress-bar "https://go.dev/dl/go1.17.10.linux-amd64.tar.gz"
echo '87fc728c9c731e2f74e4a999ef53cf07302d7ed3504b0839027bd9c10edaa3fd go1.17.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.17.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,gofmt} /usr/local/bin/

View File

@ -171,8 +171,12 @@ Users can also be deactivated using the [GitLab API](../../api/users.md#deactiva
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320875) in GitLab 14.0.
Administrators can enable automatic deactivation of users who have not signed in, or have no activity
in the last 90 days. To do this:
Administrators can enable automatic deactivation of users who either:
- Were created more than a week ago and have not signed in.
- Have no activity in the last 90 days.
To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.

View File

@ -9,6 +9,22 @@ module BulkImports
relation_name 'releases'
extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
def after_run(_context)
super
portable.releases.find_each do |release|
create_release_evidence(release)
end
end
private
def create_release_evidence(release)
return if release.historical_release? || release.upcoming_release?
::Releases::CreateEvidenceWorker.perform_async(release.id)
end
end
end
end

View File

@ -10933,9 +10933,6 @@ msgstr ""
msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
msgstr ""
msgid "Cue dramatic background music..."
msgstr ""
msgid "Current"
msgstr ""

View File

@ -0,0 +1,229 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe Pajamas::ButtonComponent, type: :component do
subject do
described_class.new(**options)
end
let(:content) { "Button content" }
let(:options) { {} }
describe 'basic usage' do
before do
render_inline(subject) do |c|
content
end
end
it 'renders its content' do
expect(rendered_component).to have_text content
end
it 'adds default styling' do
expect(rendered_component).to have_css ".btn.btn-default.btn-md.gl-button"
end
describe 'button_options' do
let(:options) { { button_options: { id: 'baz', data: { foo: 'bar' } } } }
it 'are added to the button' do
expect(rendered_component).to have_css ".gl-button#baz[data-foo='bar']"
end
context 'with custom classes' do
let(:options) { { variant: :danger, category: :tertiary, button_options: { class: 'custom-class' } } }
it 'don\'t conflict with internal button_classes' do
expect(rendered_component).to have_css '.gl-button.btn-danger.btn-danger-tertiary.custom-class'
end
end
end
describe 'button_text_classes' do
let(:options) { { button_text_classes: 'custom-text-class' } }
it 'is added to the button text' do
expect(rendered_component).to have_css ".gl-button-text.custom-text-class"
end
end
describe 'disabled' do
context 'by default (false)' do
it 'does not have disabled styling and behavior' do
expect(rendered_component).not_to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
end
end
context 'when set to true' do
let(:options) { { disabled: true } }
it 'has disabled styling and behavior' do
expect(rendered_component).to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
end
end
end
describe 'loading' do
context 'by default (false)' do
it 'is not disabled' do
expect(rendered_component).not_to have_css ".disabled[disabled='disabled']"
end
it 'does not render a spinner' do
expect(rendered_component).not_to have_css ".gl-spinner[aria-label='Loading']"
end
end
context 'when set to true' do
let(:options) { { loading: true } }
it 'is disabled' do
expect(rendered_component).to have_css ".disabled[disabled='disabled']"
end
it 'renders a spinner' do
expect(rendered_component).to have_css ".gl-spinner[aria-label='Loading']"
end
end
end
describe 'block' do
context 'by default (false)' do
it 'is inline' do
expect(rendered_component).not_to have_css ".btn-block"
end
end
context 'when set to true' do
let(:options) { { block: true } }
it 'is block element' do
expect(rendered_component).to have_css ".btn-block"
end
end
end
describe 'selected' do
context 'by default (false)' do
it 'does not have selected styling and behavior' do
expect(rendered_component).not_to have_css ".selected"
end
end
context 'when set to true' do
let(:options) { { selected: true } }
it 'has selected styling and behavior' do
expect(rendered_component).to have_css ".selected"
end
end
end
describe 'category & variant' do
context 'with category variants' do
where(:variant) { [:default, :confirm, :danger] }
let(:options) { { variant: variant, category: :tertiary } }
with_them do
it 'renders the button in correct variant && category' do
expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}")
expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}-tertiary")
end
end
end
context 'with non-category variants' do
where(:variant) { [:dashed, :link, :reset] }
let(:options) { { variant: variant, category: :tertiary } }
with_them do
it 'renders the button in correct variant && category' do
expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}")
expect(rendered_component).not_to have_css(".#{described_class::VARIANT_CLASSES[variant]}-tertiary")
end
end
end
context 'with primary category' do
where(:variant) { [:default, :confirm, :danger] }
let(:options) { { variant: variant, category: :primary } }
with_them do
it 'renders the button in correct variant && category' do
expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}")
expect(rendered_component).not_to have_css(".#{described_class::VARIANT_CLASSES[variant]}-primary")
end
end
end
end
describe 'size' do
context 'by default (medium)' do
it 'applies medium class' do
expect(rendered_component).to have_css ".btn-md"
end
end
context 'when set to small' do
let(:options) { { size: :small } }
it "applies the small class to the button" do
expect(rendered_component).to have_css ".btn-sm"
end
end
end
describe 'icon' do
it 'has none by default' do
expect(rendered_component).not_to have_css ".gl-icon"
end
context 'with icon' do
let(:options) { { icon: 'star-o', icon_classes: 'custom-icon' } }
it 'renders an icon with custom CSS class' do
expect(rendered_component).to have_css "svg.gl-icon.gl-button-icon.custom-icon[data-testid='star-o-icon']"
expect(rendered_component).not_to have_css ".btn-icon"
end
end
context 'with icon only and no content' do
let(:content) { nil }
let(:options) { { icon: 'star-o' } }
it 'adds a "btn-icon" CSS class' do
expect(rendered_component).to have_css ".btn.btn-icon"
end
end
context 'with icon only and when loading' do
let(:content) { nil }
let(:options) { { icon: 'star-o', loading: true } }
it 'renders only a loading icon' do
expect(rendered_component).not_to have_css "svg.gl-icon.gl-button-icon.custom-icon[data-testid='star-o-icon']"
expect(rendered_component).to have_css ".gl-spinner[aria-label='Loading']"
end
end
end
describe 'link button' do
it 'renders a button tag with type="button" when "href" is not set' do
expect(rendered_component).to have_css "button[type='button']"
end
context 'when "href" is provided' do
let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
it "renders a link instead of the button" do
expect(rendered_component).not_to have_css "button[type='button']"
expect(rendered_component).to have_css "a[href='https://gitlab.com'][target='_blank']"
end
end
end
end
end

View File

@ -78,10 +78,8 @@ describe('Pipelines stage component', () => {
});
it('displays loading state while jobs are being fetched', () => {
const expectedLoadingText = `${PipelineStage.i18n.loadingTextLineOne} ${PipelineStage.i18n.loadingTextLineTwo}`;
expect(findLoadingState().exists()).toBe(true);
expect(findLoadingState().text()).toBe(expectedLoadingText);
expect(findLoadingState().text()).toBe(PipelineStage.i18n.loadingText);
});
it('does not display loading state after jobs have been fetched', async () => {

View File

@ -1,4 +1,3 @@
import { GlCard } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RepoDropdown from '~/projects/compare/components/repo_dropdown.vue';
import RevisionCard from '~/projects/compare/components/revision_card.vue';
@ -14,9 +13,6 @@ describe('RepoDropdown component', () => {
...defaultProps,
...props,
},
stubs: {
GlCard,
},
});
};
@ -29,8 +25,10 @@ describe('RepoDropdown component', () => {
createComponent();
});
const RevisionCardWrapper = () => wrapper.find('.revision-card');
it('displays revision text', () => {
expect(wrapper.find(GlCard).text()).toContain(defaultProps.revisionText);
expect(RevisionCardWrapper().text()).toContain(defaultProps.revisionText);
});
it('renders RepoDropdown component', () => {

View File

@ -34,7 +34,8 @@ describe('RegistrationDropdown', () => {
const findRegistrationInstructionsDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const findTokenDropdownItem = () => wrapper.findComponent(GlDropdownForm);
const findRegistrationToken = () => wrapper.findComponent(RegistrationToken);
const findRegistrationTokenInput = () => wrapper.find('[name=token-value]');
const findRegistrationTokenInput = () =>
wrapper.findByLabelText(RegistrationToken.i18n.registrationToken);
const findTokenResetDropdownItem = () =>
wrapper.findComponent(RegistrationTokenResetDropdownItem);
const findModal = () => wrapper.findComponent(GlModal);
@ -172,10 +173,10 @@ describe('RegistrationDropdown', () => {
await nextTick();
};
it('Updates token in input', async () => {
it('Updates token input', async () => {
createComponent({}, mount);
expect(findRegistrationTokenInput().props('value')).not.toBe(newToken);
expect(findRegistrationToken().props('value')).not.toBe(newToken);
await resetToken();

View File

@ -29,6 +29,7 @@ describe('RegistrationToken', () => {
wrapper = mountFn(RegistrationToken, {
propsData: {
value: mockToken,
inputId: 'token-value',
...props,
},
localVue,

View File

@ -45,11 +45,11 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [with_index]))
end
pipeline.run
end
it 'imports release into destination project' do
pipeline.run
expect(project.releases.count).to eq(1)
imported_release = project.releases.last
@ -78,6 +78,8 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
let(:attributes) {{ 'links' => [link] }}
it 'restores release links' do
pipeline.run
release_link = project.releases.last.links.first
aggregate_failures do
@ -105,6 +107,8 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
let(:attributes) {{ 'milestone_releases' => [{ 'milestone' => milestone }] }}
it 'restores release milestone' do
pipeline.run
release_milestone = project.releases.last.milestone_releases.first.milestone
aggregate_failures do
@ -118,5 +122,33 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
end
end
end
context 'evidences' do
it 'creates release evidence' do
expect(::Releases::CreateEvidenceWorker).to receive(:perform_async)
pipeline.run
end
context 'when release is historical' do
let(:attributes) {{ 'released_at' => '2018-12-26T10:17:14.621Z' }}
it 'does not create release evidence' do
expect(::Releases::CreateEvidenceWorker).not_to receive(:perform_async)
pipeline.run
end
end
context 'when release is upcoming' do
let(:attributes) {{ 'released_at' => Time.zone.now + 30.days }}
it 'does not create release evidence' do
expect(::Releases::CreateEvidenceWorker).not_to receive(:perform_async)
pipeline.run
end
end
end
end
end

View File

@ -6637,8 +6637,10 @@ RSpec.describe User do
describe '.with_no_activity' do
it 'returns users with no activity' do
freeze_time do
not_that_long_ago = (described_class::MINIMUM_INACTIVE_DAYS - 1).days.ago.to_date
too_long_ago = described_class::MINIMUM_INACTIVE_DAYS.days.ago.to_date
active_not_that_long_ago = (described_class::MINIMUM_INACTIVE_DAYS - 1).days.ago.to_date
active_too_long_ago = described_class::MINIMUM_INACTIVE_DAYS.days.ago.to_date
created_recently = (described_class::MINIMUM_DAYS_CREATED - 1).days.ago.to_date
created_not_recently = described_class::MINIMUM_DAYS_CREATED.days.ago.to_date
create(:user, :deactivated, last_activity_on: nil)
@ -6646,12 +6648,13 @@ RSpec.describe User do
create(:user, state: :active, user_type: user_type, last_activity_on: nil)
end
create(:user, last_activity_on: not_that_long_ago)
create(:user, last_activity_on: too_long_ago)
create(:user, last_activity_on: active_not_that_long_ago)
create(:user, last_activity_on: active_too_long_ago)
create(:user, last_activity_on: nil, created_at: created_recently)
user_with_no_activity = create(:user, last_activity_on: nil)
old_enough_user_with_no_activity = create(:user, last_activity_on: nil, created_at: created_not_recently)
expect(described_class.with_no_activity).to contain_exactly(user_with_no_activity)
expect(described_class.with_no_activity).to contain_exactly(old_enough_user_with_no_activity)
end
end
end

View File

@ -6,11 +6,12 @@ RSpec.describe Oauth::TokensController do
let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
let(:other_headers) { {} }
let(:headers) { cors_request_headers.merge(other_headers)}
let(:allowed_methods) { 'POST, OPTIONS' }
shared_examples 'cross-origin POST request' do
it 'allows cross-origin requests' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
expect(response.headers['Access-Control-Allow-Methods']).to eq allowed_methods
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end
@ -23,7 +24,7 @@ RSpec.describe Oauth::TokensController do
it 'allows cross-origin requests' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
expect(response.headers['Access-Control-Allow-Methods']).to eq allowed_methods
expect(response.headers['Access-Control-Allow-Headers']).to eq 'Authorization'
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end

View File

@ -98,7 +98,7 @@ RSpec.describe 'OpenID Connect requests' do
shared_examples 'cross-origin GET and POST request' do
it 'allows cross-origin request' do
expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD, POST'
expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD, POST, OPTIONS'
expect(response.headers['Access-Control-Allow-Headers']).to be_nil
expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
end

View File

@ -7,7 +7,8 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
describe '#perform' do
let_it_be(:dormant) { create(:user, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date) }
let_it_be(:inactive) { create(:user, last_activity_on: nil) }
let_it_be(:inactive) { create(:user, last_activity_on: nil, created_at: User::MINIMUM_DAYS_CREATED.days.ago.to_date) }
let_it_be(:inactive_recently_created) { create(:user, last_activity_on: nil, created_at: (User::MINIMUM_DAYS_CREATED - 1).days.ago.to_date) }
subject(:worker) { described_class.new }
@ -71,6 +72,12 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
expect(human_user.reload.state).to eq('blocked')
expect(service_user.reload.state).to eq('blocked')
end
it 'does not deactivate recently created users' do
worker.perform
expect(inactive_recently_created.reload.state).to eq('active')
end
end
context 'when automatic deactivation of dormant users is disabled' do