Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3d62377d24
commit
fc32942743
|
|
@ -2,13 +2,12 @@
|
|||
import {
|
||||
GlBadge,
|
||||
GlDisclosureDropdown,
|
||||
GlDisclosureDropdownItem,
|
||||
GlTooltipDirective,
|
||||
GlResizeObserverDirective,
|
||||
} from '@gitlab/ui';
|
||||
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
|
||||
import { sprintf } from '~/locale';
|
||||
import { JOB_DROPDOWN, SINGLE_JOB } from '../constants';
|
||||
import PipelineMiniGraphJobItem from '~/ci/pipeline_mini_graph/job_item.vue';
|
||||
import { JOB_DROPDOWN } from '../constants';
|
||||
import JobItem from './job_item.vue';
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +21,7 @@ export default {
|
|||
JobItem,
|
||||
GlBadge,
|
||||
GlDisclosureDropdown,
|
||||
GlDisclosureDropdownItem,
|
||||
PipelineMiniGraphJobItem,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -51,7 +50,6 @@ export default {
|
|||
},
|
||||
jobItemTypes: {
|
||||
jobDropdown: JOB_DROPDOWN,
|
||||
singleJob: SINGLE_JOB,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -63,8 +61,8 @@ export default {
|
|||
computedJobId() {
|
||||
return this.pipelineId > -1 ? `${this.group.name}-${this.pipelineId}` : '';
|
||||
},
|
||||
jobStatusText() {
|
||||
return this.jobItemTooltip(this.group);
|
||||
dropdownTooltip() {
|
||||
return !this.showTooltip ? this.group?.status?.tooltip || this.group?.status?.text : '';
|
||||
},
|
||||
placement() {
|
||||
// MR !49053:
|
||||
|
|
@ -74,32 +72,8 @@ export default {
|
|||
// https://gitlab.com/gitlab-org/gitlab-ui/-/issues/2615
|
||||
return this.isMobile ? 'bottom-start' : 'right-start';
|
||||
},
|
||||
moreActionsTooltip() {
|
||||
return !this.showTooltip ? this.jobStatusText : '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
pipelineActionRequestComplete() {
|
||||
this.$emit('pipelineActionRequestComplete');
|
||||
},
|
||||
jobItem(job) {
|
||||
return {
|
||||
text: job.name,
|
||||
href: job.status?.detailsPath,
|
||||
};
|
||||
},
|
||||
jobItemTooltip(job) {
|
||||
const { tooltip: statusTooltip } = job.status;
|
||||
const { text: statusText } = job.status;
|
||||
|
||||
if (statusTooltip) {
|
||||
if (this.isDelayedJob) {
|
||||
return sprintf(statusTooltip, { remainingTime: job.remainingTime });
|
||||
}
|
||||
return statusTooltip;
|
||||
}
|
||||
return statusText;
|
||||
},
|
||||
handleResize() {
|
||||
this.isMobile = GlBreakpointInstance.getBreakpointSize() === 'xs';
|
||||
},
|
||||
|
|
@ -117,8 +91,7 @@ export default {
|
|||
:id="computedJobId"
|
||||
v-gl-resize-observer="handleResize"
|
||||
v-gl-tooltip.viewport.left="{ customClass: 'ci-job-component-tooltip' }"
|
||||
:title="moreActionsTooltip"
|
||||
class="ci-job-group-dropdown"
|
||||
:title="dropdownTooltip"
|
||||
block
|
||||
fluid-width
|
||||
:placement="placement"
|
||||
|
|
@ -141,26 +114,13 @@ export default {
|
|||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<gl-disclosure-dropdown-item
|
||||
v-for="job in group.jobs"
|
||||
:key="job.id"
|
||||
v-gl-tooltip.viewport.left="{
|
||||
title: jobItemTooltip(job),
|
||||
customClass: 'ci-job-component-tooltip',
|
||||
}"
|
||||
:item="jobItem(job)"
|
||||
>
|
||||
<template #list-item>
|
||||
<job-item
|
||||
:is-link="false"
|
||||
:job="job"
|
||||
:type="$options.jobItemTypes.singleJob"
|
||||
css-class-job-name="gl-p-3"
|
||||
hide-tooltip
|
||||
@pipelineActionRequestComplete="pipelineActionRequestComplete"
|
||||
/>
|
||||
</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
<ul class="gl-m-0 gl-w-34 gl-overflow-y-auto gl-p-0" @click.stop>
|
||||
<pipeline-mini-graph-job-item
|
||||
v-for="job in group.jobs"
|
||||
:key="job.id"
|
||||
:job="job"
|
||||
@jobActionExecuted="$emit('pipelineActionRequestComplete')"
|
||||
/>
|
||||
</ul>
|
||||
</gl-disclosure-dropdown>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export default {
|
|||
};
|
||||
},
|
||||
status() {
|
||||
return this.job.detailedStatus || {};
|
||||
return this.job.detailedStatus || this.job.status;
|
||||
},
|
||||
tooltipText() {
|
||||
const statusTooltip = capitalizeFirstCharacter(this.status?.tooltip);
|
||||
|
|
@ -49,7 +49,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-disclosure-dropdown-item :item="item" class="ci-job-component" data-testid="job-item">
|
||||
<gl-disclosure-dropdown-item :item="item" class="ci-job-component" data-testid="ci-job-item">
|
||||
<template #list-item>
|
||||
<div class="-gl-my-2 gl-flex gl-items-center gl-justify-between">
|
||||
<job-name-component
|
||||
|
|
|
|||
|
|
@ -950,6 +950,7 @@ export default {
|
|||
@deleteWorkItemError="issuesError = __('An error occurred while deleting an issuable.')"
|
||||
@workItemDeleted="deleteIssuable"
|
||||
@promotedToObjective="promoteToObjective"
|
||||
@workItemTypeChanged="updateIssuablesCache($event)"
|
||||
/>
|
||||
<issuable-list
|
||||
v-if="hasAnyIssues"
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ export function mapWorkItemWidgetsToIssuableFields({
|
|||
|
||||
activeItem.title = workItem.title;
|
||||
activeItem.confidential = workItem.confidential;
|
||||
activeItem.type = workItem?.workItemType?.name?.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,11 +175,6 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isDrawer: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
hideSubscribe: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -313,7 +308,7 @@ export default {
|
|||
: this.$options.i18n.confidentialityEnabled;
|
||||
},
|
||||
showChangeType() {
|
||||
return !(this.isEpic || this.isDrawer) && this.glFeatures.workItemsBeta;
|
||||
return !this.isEpic && this.glFeatures.workItemsBeta;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -666,6 +666,7 @@ export default {
|
|||
},
|
||||
workItemTypeChanged() {
|
||||
this.$apollo.queries.workItem.refetch();
|
||||
this.$emit('workItemTypeChanged', this.workItem);
|
||||
},
|
||||
},
|
||||
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
|
||||
|
|
@ -784,7 +785,6 @@ export default {
|
|||
:work-item-reference="workItem.reference"
|
||||
:work-item-create-note-email="workItem.createNoteEmail"
|
||||
:is-modal="isModal"
|
||||
:is-drawer="isDrawer"
|
||||
:work-item-state="workItem.state"
|
||||
:has-children="hasChildren"
|
||||
:has-parent="shouldShowAncestors"
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ export default {
|
|||
is-drawer
|
||||
class="work-item-drawer !gl-pt-0 xl:!gl-px-6"
|
||||
@deleteWorkItem="deleteWorkItem"
|
||||
@workItemTypeChanged="$emit('workItemTypeChanged', $event)"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -294,21 +294,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.stage-column .ci-job-group-dropdown {
|
||||
.stage-column {
|
||||
// stylelint-disable-next-line gitlab/no-gl-class
|
||||
&,
|
||||
.gl-new-dropdown-custom-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Reset padding, as inner element will
|
||||
// define padding
|
||||
// stylelint-disable-next-line gitlab/no-gl-class
|
||||
.gl-new-dropdown-item-content,
|
||||
.gl-new-dropdown-item-text-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// Set artificial focus on the menu-item to keep
|
||||
// it consistent with the original dropdown items
|
||||
// stylelint-disable-next-line gitlab/no-gl-class
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:issues_list_drawer, project)
|
||||
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
|
||||
push_force_frontend_feature_flag(:glql_integration, project&.glql_integration_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_beta, project&.work_items_beta_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_alpha, project&.work_items_alpha_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
|
|
@ -63,7 +64,6 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
|
||||
before_action only: :show do
|
||||
push_frontend_feature_flag(:work_items_beta, project&.group)
|
||||
push_force_frontend_feature_flag(:work_items_beta, project&.work_items_beta_feature_flag_enabled?)
|
||||
push_frontend_feature_flag(:epic_widget_edit_confirmation, project)
|
||||
push_frontend_feature_flag(:namespace_level_work_items, project&.group)
|
||||
push_frontend_feature_flag(:work_items_view_preference, current_user)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ module Types
|
|||
|
||||
abilities :read_issue, :admin_issue, :update_issue, :reopen_issue,
|
||||
:read_design, :create_design, :destroy_design,
|
||||
:create_note, :update_design, :admin_issue_relation
|
||||
:create_note, :update_design, :move_design,
|
||||
:admin_issue_relation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module Types
|
|||
:admin_remote_mirror, :create_label, :update_wiki, :destroy_wiki,
|
||||
:create_pages, :destroy_pages, :read_pages_content, :admin_operations,
|
||||
:read_merge_request, :read_design, :create_design, :update_design, :destroy_design,
|
||||
:read_environment, :view_edit_page
|
||||
:move_design, :read_environment, :view_edit_page
|
||||
|
||||
permission_field :create_snippet
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,19 @@ module AccessTokensHelper
|
|||
end
|
||||
|
||||
def expires_at_field_data
|
||||
return {} unless Gitlab::CurrentSettings.require_personal_access_token_expiry?
|
||||
|
||||
{
|
||||
min_date: 1.day.from_now.iso8601
|
||||
min_date: 1.day.from_now.iso8601,
|
||||
max_date: max_date_allowed
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def max_date_allowed
|
||||
return unless Gitlab::CurrentSettings.require_personal_access_token_expiry?
|
||||
|
||||
::PersonalAccessToken.max_expiration_lifetime_in_days.days.from_now.iso8601
|
||||
end
|
||||
end
|
||||
|
||||
AccessTokensHelper.prepend_mod
|
||||
|
|
|
|||
|
|
@ -66,14 +66,17 @@ swap:
|
|||
pop-up: "dialog"
|
||||
popup: "dialog"
|
||||
repo: "repository"
|
||||
root group: "top-level group"
|
||||
signed in user: "authenticated user"
|
||||
signed-in user: "authenticated user"
|
||||
since: "because' or 'after"
|
||||
source (?:install|installation): self-compiled installation
|
||||
source (?:installs|installations): self-compiled installations
|
||||
sub group: "subgroup"
|
||||
sub-group: "subgroup"
|
||||
sub-groups: "subgroups"
|
||||
timezone: "time zone"
|
||||
top level group: "top-level group"
|
||||
utiliz(?:es?|ing): "use"
|
||||
VSCode: "VS Code"
|
||||
we recommend: "you should"
|
||||
|
|
|
|||
|
|
@ -27147,6 +27147,7 @@ Check permissions for the current user on a issue.
|
|||
| <a id="issuepermissionscreatedesign"></a>`createDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_design` on this resource. |
|
||||
| <a id="issuepermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
|
||||
| <a id="issuepermissionsdestroydesign"></a>`destroyDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_design` on this resource. |
|
||||
| <a id="issuepermissionsmovedesign"></a>`moveDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `move_design` on this resource. |
|
||||
| <a id="issuepermissionsreaddesign"></a>`readDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_design` on this resource. |
|
||||
| <a id="issuepermissionsreadissue"></a>`readIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_issue` on this resource. |
|
||||
| <a id="issuepermissionsreopenissue"></a>`reopenIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `reopen_issue` on this resource. |
|
||||
|
|
@ -33719,6 +33720,7 @@ Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction).
|
|||
| <a id="projectpermissionsdownloadcode"></a>`downloadCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_code` on this resource. |
|
||||
| <a id="projectpermissionsdownloadwikicode"></a>`downloadWikiCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_wiki_code` on this resource. |
|
||||
| <a id="projectpermissionsforkproject"></a>`forkProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `fork_project` on this resource. |
|
||||
| <a id="projectpermissionsmovedesign"></a>`moveDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `move_design` on this resource. |
|
||||
| <a id="projectpermissionspushcode"></a>`pushCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_code` on this resource. |
|
||||
| <a id="projectpermissionspushtodeleteprotectedbranch"></a>`pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_to_delete_protected_branch` on this resource. |
|
||||
| <a id="projectpermissionsreadcommitstatus"></a>`readCommitStatus` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_commit_status` on this resource. |
|
||||
|
|
|
|||
|
|
@ -1378,6 +1378,13 @@ Do not use:
|
|||
|
||||
- GitLab Runner Kubernetes executor, because this can infringe on the Kubernetes trademark.
|
||||
|
||||
## language model, large language model
|
||||
|
||||
When referring to language models, be precise. Not all language models are large,
|
||||
and not all models are language models. When in doubt, ask a developer or PM for confirmation.
|
||||
|
||||
You can use LLM to refer to a large language model if you spell it out on first use.
|
||||
|
||||
## later
|
||||
|
||||
Use **later** when talking about version numbers.
|
||||
|
|
@ -1615,6 +1622,10 @@ Use:
|
|||
- The GitLab model registry supports A, B, and C.
|
||||
- You can publish a model to your project's model registry.
|
||||
|
||||
## models
|
||||
|
||||
For usage, see [language models](#language-model-large-language-model).
|
||||
|
||||
## n/a, N/A, not applicable
|
||||
|
||||
When possible, use **not applicable**. Spelling out the phrase helps non-English speaking users and avoids
|
||||
|
|
|
|||
|
|
@ -708,6 +708,28 @@ Google Workspace Administrator also provides the IdP metadata, Entity ID, and SH
|
|||
fingerprint. However, GitLab does not need this information to connect to the
|
||||
Google Workspace SAML application.
|
||||
|
||||
### Set up Microsoft Entra ID
|
||||
|
||||
1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/).
|
||||
1. [Create a non-gallery application](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/overview-application-gallery#create-your-own-application).
|
||||
1. [Configure SSO for that application](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal-setup-sso).
|
||||
|
||||
The following settings in your `gitlab.rb` file correspond to the Microsoft Entra ID fields:
|
||||
|
||||
| `gitlab.rb` setting | Microsoft Entra ID field |
|
||||
| ------------------------------------| ---------------------------------------------- |
|
||||
| `issuer` | **Identifier (Entity ID)** |
|
||||
| `assertion_consumer_service_url` | **Reply URL (Assertion Consumer Service URL)** |
|
||||
| `idp_sso_target_url` | **Login URL** |
|
||||
| `idp_cert_fingerprint` | **Thumbprint** |
|
||||
|
||||
1. Set the following attributes:
|
||||
- **Unique User Identifier (Name ID)** to `user.objectID`.
|
||||
- **Name identifier format** to `persistent`. For more information, see how to [manage user SAML identity](../user/group/saml_sso/index.md#manage-user-saml-identity).
|
||||
- **Additional claims** to [supported attributes](#configure-assertions).
|
||||
|
||||
For more information, see an [example configuration page](../user/group/saml_sso/example_saml_config.md#azure-active-directory).
|
||||
|
||||
### Set up other IdPs
|
||||
|
||||
Some IdPs have documentation on how to use them as the IdP in SAML configurations.
|
||||
|
|
@ -3222,6 +3244,12 @@ such as the following:
|
|||
|
||||
For example configurations, see the [notes on specific providers](#set-up-identity-providers).
|
||||
|
||||
## Configure SAML with Geo
|
||||
|
||||
To configure Geo with SAML, see [Configuring instance-wide SAML](../administration/geo/replication/single_sign_on.md#configuring-instance-wide-saml).
|
||||
|
||||
For more information, see [Geo with Single Sign On (SSO)](../administration/geo/replication/single_sign_on.md).
|
||||
|
||||
## Glossary
|
||||
|
||||
| Term | Description |
|
||||
|
|
|
|||
|
|
@ -120,17 +120,13 @@ module QA
|
|||
|
||||
def has_skipped_job_in_group?
|
||||
within_element('disclosure-content') do
|
||||
all_elements('ci-job-item', minimum: 1).all? do
|
||||
has_selector?('.ci-status-icon-skipped')
|
||||
end
|
||||
has_selector?('[aria-label="Status: Skipped"]')
|
||||
end
|
||||
end
|
||||
|
||||
def has_no_skipped_job_in_group?
|
||||
within_element('disclosure-content') do
|
||||
all_elements('ci-job-item', minimum: 1).all? do
|
||||
has_no_selector?('.ci-status-icon-skipped')
|
||||
end
|
||||
has_no_selector?('[aria-label="Status: Skipped"]')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ spec/frontend/ci/job_details/components/log/line_header_spec.js
|
|||
spec/frontend/ci/job_details/components/log/line_spec.js
|
||||
spec/frontend/ci/job_details/components/log/log_spec.js
|
||||
spec/frontend/ci/job_details/components/sidebar/job_sidebar_retry_button_spec.js
|
||||
spec/frontend/ci/pipeline_details/graph/components/job_group_dropdown_spec.js
|
||||
spec/frontend/ci/pipeline_details/header/components/header_badges_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/header/validation_segment_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
|
|||
|
||||
wait_for_requests
|
||||
|
||||
within first('[data-testid="job-item"]') do
|
||||
within first('[data-testid="ci-job-item"]') do
|
||||
expect(find_by_testid('play-icon')).to be_visible
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { shallowMount, mount } from '@vue/test-utils';
|
||||
import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui';
|
||||
import { GlDisclosureDropdown } from '@gitlab/ui';
|
||||
|
||||
import PipelineMiniGraphJobItem from '~/ci/pipeline_mini_graph/job_item.vue';
|
||||
import JobGroupDropdown from '~/ci/pipeline_details/graph/components/job_group_dropdown.vue';
|
||||
import JobItem from '~/ci/pipeline_details/graph/components/job_item.vue';
|
||||
import { SINGLE_JOB } from '~/ci/pipeline_details/graph/constants';
|
||||
|
||||
describe('job group dropdown component', () => {
|
||||
const group = {
|
||||
|
|
@ -70,7 +70,7 @@ describe('job group dropdown component', () => {
|
|||
const findJobItem = () => wrapper.findComponent(JobItem);
|
||||
const findTriggerButton = () => wrapper.find('button');
|
||||
const findDisclosureDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
|
||||
const findDisclosureDropdownItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem);
|
||||
const findPipelineMiniGraphJobItems = () => wrapper.findAllComponents(PipelineMiniGraphJobItem);
|
||||
|
||||
const createComponent = ({ props, mountFn = shallowMount } = {}) => {
|
||||
wrapper = mountFn(JobGroupDropdown, {
|
||||
|
|
@ -81,14 +81,6 @@ describe('job group dropdown component', () => {
|
|||
});
|
||||
};
|
||||
|
||||
it('renders dropdown with jobs', () => {
|
||||
createComponent({ mountFn: mount });
|
||||
|
||||
expect(wrapper.findAll('[data-testid="disclosure-content"] > li').length).toBe(
|
||||
group.jobs.length,
|
||||
);
|
||||
});
|
||||
|
||||
it('renders dropdown', () => {
|
||||
createComponent();
|
||||
|
||||
|
|
@ -125,31 +117,12 @@ describe('job group dropdown component', () => {
|
|||
it('renders parallel jobs in group', () => {
|
||||
createComponent({ mountFn: mount });
|
||||
|
||||
const [item1, item2] = findDisclosureDropdownItems().wrappers;
|
||||
const [item1, item2] = findPipelineMiniGraphJobItems().wrappers;
|
||||
|
||||
expect(findDisclosureDropdownItems()).toHaveLength(2);
|
||||
expect(findPipelineMiniGraphJobItems()).toHaveLength(2);
|
||||
|
||||
expect(item1.props('item')).toEqual({
|
||||
text: group.jobs[0].name,
|
||||
href: group.jobs[0].status.detailsPath,
|
||||
});
|
||||
expect(item1.findComponent(JobItem).props()).toMatchObject({
|
||||
isLink: false,
|
||||
job: group.jobs[0],
|
||||
type: SINGLE_JOB,
|
||||
cssClassJobName: 'gl-p-3',
|
||||
});
|
||||
|
||||
expect(item2.props('item')).toEqual({
|
||||
text: group.jobs[1].name,
|
||||
href: group.jobs[1].status.detailsPath,
|
||||
});
|
||||
expect(item2.findComponent(JobItem).props()).toMatchObject({
|
||||
isLink: false,
|
||||
job: group.jobs[1],
|
||||
type: SINGLE_JOB,
|
||||
cssClassJobName: 'gl-p-3',
|
||||
});
|
||||
expect(item1.props('job')).toEqual(group.jobs[0]);
|
||||
expect(item2.props('job')).toEqual(group.jobs[1]);
|
||||
});
|
||||
|
||||
describe('tooltip', () => {
|
||||
|
|
|
|||
|
|
@ -6,17 +6,25 @@ import JobNameComponent from '~/ci/common/private/job_name_component.vue';
|
|||
|
||||
import { mockPipelineJob } from './mock_data';
|
||||
|
||||
const { detailedStatus, ...mockJobInfo } = mockPipelineJob;
|
||||
|
||||
const mockJobDetailedStatus = {
|
||||
...mockJobInfo,
|
||||
detailedStatus,
|
||||
};
|
||||
|
||||
const mockJobStatus = {
|
||||
...mockJobInfo,
|
||||
status: detailedStatus,
|
||||
};
|
||||
|
||||
describe('JobItem', () => {
|
||||
let wrapper;
|
||||
|
||||
const defaultProps = {
|
||||
job: mockPipelineJob,
|
||||
};
|
||||
|
||||
const createComponent = ({ props = {} } = {}) => {
|
||||
wrapper = shallowMount(JobItem, {
|
||||
propsData: {
|
||||
...defaultProps,
|
||||
job: mockPipelineJob,
|
||||
...props,
|
||||
},
|
||||
});
|
||||
|
|
@ -25,9 +33,12 @@ describe('JobItem', () => {
|
|||
const findJobNameComponent = () => wrapper.findComponent(JobNameComponent);
|
||||
const findJobActionButton = () => wrapper.findComponent(JobActionButton);
|
||||
|
||||
describe('when mounted', () => {
|
||||
describe.each([
|
||||
['has detailedStatus', mockJobDetailedStatus],
|
||||
['has status', mockJobStatus],
|
||||
])('when job contains "%s"', (_, job) => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
createComponent({ props: { job } });
|
||||
});
|
||||
|
||||
describe('job name', () => {
|
||||
|
|
@ -37,13 +48,13 @@ describe('JobItem', () => {
|
|||
|
||||
it('sends the necessary props to the job name component', () => {
|
||||
expect(findJobNameComponent().props()).toMatchObject({
|
||||
name: mockPipelineJob.name,
|
||||
status: mockPipelineJob.detailedStatus,
|
||||
name: mockJobInfo.name,
|
||||
status: detailedStatus,
|
||||
});
|
||||
});
|
||||
|
||||
it('sets the correct tooltip for the job item', () => {
|
||||
const tooltip = capitalizeFirstCharacter(mockPipelineJob.detailedStatus.tooltip);
|
||||
const tooltip = capitalizeFirstCharacter(detailedStatus.tooltip);
|
||||
|
||||
expect(findJobNameComponent().attributes('title')).toBe(tooltip);
|
||||
});
|
||||
|
|
@ -57,9 +68,9 @@ describe('JobItem', () => {
|
|||
|
||||
it('sends the necessary props to the job action button', () => {
|
||||
expect(findJobActionButton().props()).toMatchObject({
|
||||
jobId: mockPipelineJob.id,
|
||||
jobAction: mockPipelineJob.detailedStatus.action,
|
||||
jobName: mockPipelineJob.name,
|
||||
jobId: mockJobInfo.id,
|
||||
jobAction: detailedStatus.action,
|
||||
jobName: mockJobInfo.name,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ describe('WorkItemActions component', () => {
|
|||
hasChildren = false,
|
||||
canCreateRelatedItem = true,
|
||||
workItemsBeta = true,
|
||||
isDrawer = false,
|
||||
} = {}) => {
|
||||
wrapper = shallowMountExtended(WorkItemActions, {
|
||||
isLoggedIn: isLoggedIn(),
|
||||
|
|
@ -160,7 +159,6 @@ describe('WorkItemActions component', () => {
|
|||
hideSubscribe,
|
||||
hasChildren,
|
||||
canCreateRelatedItem,
|
||||
isDrawer,
|
||||
},
|
||||
mocks: {
|
||||
$toast,
|
||||
|
|
@ -623,11 +621,5 @@ describe('WorkItemActions component', () => {
|
|||
|
||||
expect(findChangeTypeButton().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('hides the action in case of drawer', () => {
|
||||
createComponent({ isDrawer: true });
|
||||
|
||||
expect(findChangeTypeButton().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ RSpec.describe Types::PermissionTypes::Issue do
|
|||
expected_permissions = [
|
||||
:read_issue, :admin_issue, :update_issue, :reopen_issue,
|
||||
:read_design, :create_design, :destroy_design,
|
||||
:create_note, :update_design, :admin_issue_relation
|
||||
:create_note, :update_design, :move_design,
|
||||
:admin_issue_relation
|
||||
]
|
||||
|
||||
expected_permissions.each do |permission|
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ RSpec.describe Types::PermissionTypes::Project do
|
|||
:create_merge_request_from, :create_wiki, :push_code, :create_deployment, :push_to_delete_protected_branch,
|
||||
:admin_wiki, :admin_project, :update_pages, :admin_remote_mirror, :create_label,
|
||||
:update_wiki, :destroy_wiki, :create_pages, :destroy_pages, :read_pages_content,
|
||||
:read_merge_request, :read_design, :create_design, :update_design, :destroy_design, :read_environment,
|
||||
:view_edit_page
|
||||
:read_merge_request, :read_design, :create_design, :update_design, :destroy_design, :move_design,
|
||||
:read_environment, :view_edit_page
|
||||
]
|
||||
|
||||
expected_permissions.each do |permission|
|
||||
|
|
|
|||
|
|
@ -67,19 +67,29 @@ RSpec.describe AccessTokensHelper, feature_category: :system_access do
|
|||
end
|
||||
|
||||
describe '#expires_at_field_data', :freeze_time do
|
||||
before do
|
||||
# Test the CE version of `expires_at_field_data` by satisfying the condition in the EE
|
||||
# that calls the `super` method.
|
||||
allow(helper).to receive(:personal_access_token_expiration_policy_enabled?).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns expected hash' do
|
||||
expect(helper.expires_at_field_data).to eq({
|
||||
min_date: 1.day.from_now.iso8601
|
||||
min_date: 1.day.from_now.iso8601,
|
||||
max_date: 400.days.from_now.iso8601
|
||||
})
|
||||
end
|
||||
|
||||
context 'when require_personal_access_token_expiry is true' do
|
||||
context 'when require_personal_access_token_expiry is false' do
|
||||
before do
|
||||
stub_application_setting(require_personal_access_token_expiry: false)
|
||||
end
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(helper.expires_at_field_data).to eq({})
|
||||
expect(helper.expires_at_field_data).to eq({
|
||||
min_date: 1.day.from_now.iso8601,
|
||||
max_date: nil
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue