Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-11-16 18:12:21 +00:00
parent 3563f19374
commit c1436508fa
128 changed files with 321 additions and 645 deletions

View File

@ -2558,7 +2558,6 @@ Style/OpenStructUse:
- 'ee/spec/graphql/ee/resolvers/board_lists_resolver_spec.rb'
- 'ee/spec/graphql/mutations/merge_requests/accept_spec.rb'
- 'ee/spec/graphql/resolvers/board_groupings/epics_resolvers_spec.rb'
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
- 'ee/spec/helpers/ee/blob_helper_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb'
- 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'

View File

@ -17,4 +17,7 @@ export default CodeBlockHighlight.extend({
addNodeView() {
return new VueNodeViewRenderer(FrontmatterWrapper);
},
addInputRules() {
return [];
},
});

View File

@ -1,57 +0,0 @@
<script>
import { mapState, mapActions } from 'vuex';
import { s__ } from '~/locale';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { sortableFields } from '../utils';
import PackageTypeToken from './tokens/package_type_token.vue';
export default {
tokens: [
{
type: 'type',
icon: 'package',
title: s__('PackageRegistry|Type'),
unique: true,
token: PackageTypeToken,
operators: OPERATOR_IS_ONLY,
},
],
components: { RegistrySearch, UrlSync },
computed: {
...mapState({
isGroupPage: (state) => state.config.isGroupPage,
sorting: (state) => state.sorting,
filter: (state) => state.filter,
}),
sortableFields() {
return sortableFields(this.isGroupPage);
},
},
methods: {
...mapActions(['setSorting', 'setFilter']),
updateSorting(newValue) {
this.setSorting(newValue);
this.$emit('update');
},
},
};
</script>
<template>
<url-sync>
<template #default="{ updateQuery }">
<registry-search
:filter="filter"
:sorting="sorting"
:tokens="$options.tokens"
:sortable-fields="sortableFields"
@sorting:changed="updateSorting"
@filter:changed="setFilter"
@filter:submit="$emit('update')"
@query:changed="updateQuery"
/>
</template>
</url-sync>
</template>

View File

@ -1,47 +0,0 @@
<script>
import { n__ } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '../constants';
export default {
name: 'PackageTitle',
components: {
TitleArea,
MetadataItem,
},
props: {
count: {
type: Number,
required: false,
default: null,
},
helpUrl: {
type: String,
required: true,
},
},
computed: {
showPackageCount() {
return Number.isInteger(this.count);
},
packageAmountText() {
return n__(`%d Package`, `%d Packages`, this.count);
},
infoMessages() {
return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
i18n: {
LIST_TITLE_TEXT,
},
};
</script>
<template>
<title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
<template #metadata-amount>
<metadata-item v-if="showPackageCount" icon="package" :text="packageAmountText" />
</template>
</title-area>
</template>

View File

@ -7,6 +7,8 @@ import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
import InfrastructureTitle from '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue';
import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
import PackageList from './packages_list.vue';
@ -16,28 +18,10 @@ export default {
GlLink,
GlSprintf,
PackageList,
PackageTitle: () =>
import(/* webpackChunkName: 'package_registry_components' */ './package_title.vue'),
PackageSearch: () =>
import(/* webpackChunkName: 'package_registry_components' */ './package_search.vue'),
InfrastructureTitle: () =>
import(
/* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue'
),
InfrastructureSearch: () =>
import(
/* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue'
),
InfrastructureTitle,
InfrastructureSearch,
},
inject: {
titleComponent: {
from: 'titleComponent',
default: 'PackageTitle',
},
searchComponent: {
from: 'searchComponent',
default: 'PackageSearch',
},
emptyPageTitle: {
from: 'emptyPageTitle',
default: s__('PackageRegistry|There are no packages yet'),
@ -111,8 +95,8 @@ export default {
<template>
<div>
<component :is="titleComponent" :help-url="packageHelpUrl" :count="packagesCount" />
<component :is="searchComponent" @update="requestPackagesList" />
<infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
<infrastructure-search @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>

View File

@ -1,26 +0,0 @@
<script>
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
import { PACKAGE_TYPES } from '../../constants';
export default {
components: {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
},
PACKAGE_TYPES,
};
</script>
<template>
<gl-filtered-search-token v-bind="{ ...$attrs }" v-on="$listeners">
<template #suggestions>
<gl-filtered-search-suggestion
v-for="(type, index) in $options.PACKAGE_TYPES"
:key="index"
:value="type.type"
>
{{ type.title }}
</gl-filtered-search-suggestion>
</template>
</gl-filtered-search-token>
</template>

View File

@ -96,10 +96,4 @@ export const PACKAGE_TYPES = [
},
];
export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');
export const LIST_INTRO_TEXT = s__(
'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
);
export const TERRAFORM_SEARCH_TYPE = Object.freeze({ value: { data: 'terraform_module' } });

View File

@ -3,6 +3,8 @@ import destroyPackageMutation from '~/packages_and_registries/package_registry/g
import createFlash from '~/flash';
import { s__ } from '~/locale';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/package_registry/constants';
export default {
props: {
refetchQueries: {
@ -18,7 +20,7 @@ export default {
},
i18n: {
errorMessage: s__('PackageRegistry|Something went wrong while deleting the package.'),
successMessage: s__('PackageRegistry|Package deleted successfully'),
successMessage: DELETE_PACKAGE_SUCCESS_MESSAGE,
},
methods: {
async deletePackage(packageEntity) {

View File

@ -3,12 +3,12 @@ import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import createFlash from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import {
PROJECT_RESOURCE_TYPE,
GROUP_RESOURCE_TYPE,
GRAPHQL_PAGE_SIZE,
DELETE_PACKAGE_SUCCESS_MESSAGE,
} from '~/packages_and_registries/package_registry/constants';
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';

View File

@ -1,6 +1,6 @@
<script>
import { s__ } from '~/locale';
import { sortableFields } from '~/packages/list/utils';
import { sortableFields } from '~/packages_and_registries/package_registry/utils';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';

View File

@ -1,6 +1,5 @@
<script>
import { n__ } from '~/locale';
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list/constants';
import { n__, s__ } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
@ -29,11 +28,14 @@ export default {
return n__(`%d Package`, `%d Packages`, this.count);
},
infoMessages() {
return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
i18n: {
LIST_TITLE_TEXT,
LIST_TITLE_TEXT: s__('PackageRegistry|Package Registry'),
LIST_INTRO_TEXT: s__(
'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
),
},
};
</script>

View File

@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
import { PACKAGE_TYPES } from '~/packages/list/constants';
import { PACKAGE_TYPES } from '~/packages_and_registries/package_registry/constants';
export default {
components: {
@ -17,9 +17,9 @@ export default {
<gl-filtered-search-suggestion
v-for="(type, index) in $options.PACKAGE_TYPES"
:key="index"
:value="type.type"
:value="type"
>
{{ type.title }}
{{ type }}
</gl-filtered-search-suggestion>
</template>
</gl-filtered-search-token>

View File

@ -1,4 +1,4 @@
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
export const PACKAGE_TYPE_CONAN = 'CONAN';
export const PACKAGE_TYPE_MAVEN = 'MAVEN';
@ -70,6 +70,8 @@ export const FETCH_PACKAGE_DETAILS_ERROR_MESSAGE = s__(
'PackageRegistry|Failed to load the package data',
);
export const DELETE_PACKAGE_SUCCESS_MESSAGE = s__('PackageRegistry|Package deleted successfully');
export const PACKAGE_ERROR_STATUS = 'ERROR';
export const PACKAGE_DEFAULT_STATUS = 'DEFAULT';
export const PACKAGE_HIDDEN_STATUS = 'HIDDEN';
@ -84,3 +86,51 @@ export const INSTANCE_PACKAGE_ENDPOINT_TYPE = 'instance';
export const PROJECT_RESOURCE_TYPE = 'project';
export const GROUP_RESOURCE_TYPE = 'group';
export const GRAPHQL_PAGE_SIZE = 20;
export const LIST_KEY_NAME = 'name';
export const LIST_KEY_PROJECT = 'project_path';
export const LIST_KEY_VERSION = 'version';
export const LIST_KEY_PACKAGE_TYPE = 'type';
export const LIST_KEY_CREATED_AT = 'created_at';
export const LIST_LABEL_NAME = __('Name');
export const LIST_LABEL_PROJECT = __('Project');
export const LIST_LABEL_VERSION = __('Version');
export const LIST_LABEL_PACKAGE_TYPE = __('Type');
export const LIST_LABEL_CREATED_AT = __('Published');
export const SORT_FIELDS = [
{
orderBy: LIST_KEY_NAME,
label: LIST_LABEL_NAME,
},
{
orderBy: LIST_KEY_PROJECT,
label: LIST_LABEL_PROJECT,
},
{
orderBy: LIST_KEY_VERSION,
label: LIST_LABEL_VERSION,
},
{
orderBy: LIST_KEY_PACKAGE_TYPE,
label: LIST_LABEL_PACKAGE_TYPE,
},
{
orderBy: LIST_KEY_CREATED_AT,
label: LIST_LABEL_CREATED_AT,
},
];
export const PACKAGE_TYPES = [
s__('PackageRegistry|Composer'),
s__('PackageRegistry|Conan'),
s__('PackageRegistry|Generic'),
s__('PackageRegistry|Maven'),
s__('PackageRegistry|npm'),
s__('PackageRegistry|NuGet'),
s__('PackageRegistry|PyPI'),
s__('PackageRegistry|RubyGems'),
s__('PackageRegistry|Debian'),
s__('PackageRegistry|Helm'),
];

View File

@ -11,6 +11,8 @@ import {
PACKAGE_TYPE_GENERIC,
PACKAGE_TYPE_DEBIAN,
PACKAGE_TYPE_HELM,
LIST_KEY_PROJECT,
SORT_FIELDS,
} from './constants';
export const getPackageTypeLabel = (packageType) => {
@ -41,3 +43,6 @@ export const getPackageTypeLabel = (packageType) => {
};
export const packageTypeToTrackCategory = (type) => `UI::${capitalize(type)}Packages`;
export const sortableFields = (isGroupPage) =>
SORT_FIELDS.filter((f) => f.orderBy !== LIST_KEY_PROJECT || isGroupPage);

View File

@ -1,4 +1,4 @@
import registryExplorer from '~/registry/explorer/index';
import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
const explorer = registryExplorer();

View File

@ -1,4 +1,4 @@
import registryExplorer from '~/registry/explorer/index';
import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
const explorer = registryExplorer();

View File

@ -5,10 +5,10 @@ import { OBSTACLE_TYPES } from './constants';
const OBSTACLE_TEXT = {
[OBSTACLE_TYPES.oncallSchedules]: s__(
'OnCallSchedules|On-call schedule %{obstacle} in Project %{project}',
'OnCallSchedules|On-call schedule %{obstacle} in project %{project}',
),
[OBSTACLE_TYPES.escalationPolicies]: s__(
'EscalationPolicies|Escalation policy %{obstacle} in Project %{project}',
'EscalationPolicies|Escalation policy %{obstacle} in project %{project}',
),
};

View File

@ -44,7 +44,6 @@ class EventsFinder
events = by_created_at_after(events)
events = sort(events)
events = events.with_associations if params[:with_associations]
paginated_filtered_by_user_visibility(events)
end
@ -113,10 +112,12 @@ class EventsFinder
end
def paginated_filtered_by_user_visibility(events)
events_count = events.count
events = events.with_associations if params[:with_associations]
limited_events = events.page(page).per(per_page)
visible_events = limited_events.select { |event| event.visible_to_user?(current_user) }
Kaminari.paginate_array(visible_events, total_count: events.count)
Kaminari.paginate_array(visible_events, total_count: events_count)
end
def per_page

View File

@ -15,7 +15,13 @@ module MergeRequests
def execute
end_position = position.line_range["end"]
diff_line_index = diff_lines.find_index { |l| l.new_line == end_position["new_line"] || l.old_line == end_position["old_line"] }
diff_line_index = diff_lines.find_index do |l|
if end_position["new_line"]
l.new_line == end_position["new_line"]
elsif end_position["old_line"]
l.old_line == end_position["old_line"]
end
end
initial_line_index = [diff_line_index - OVERFLOW_LINES_COUNT, 0].max
last_line_index = [diff_line_index + OVERFLOW_LINES_COUNT, diff_lines.length].min

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344617
milestone: '14.5'
type: development
group: group::integrations
default_enabled: false
default_enabled: true

View File

@ -41,9 +41,15 @@ swap:
developer access: the Developer role
developer permission: the Developer role
developer permissions: the Developer role
guest access: the Guest role
guest permission: the Guest role
guest permissions: the Guest role
maintainer access: the Maintainer role
maintainer permission: the Maintainer role
maintainer permissions: the Maintainer role
owner access: the Owner role
owner permission: the Owner role
owner permissions: the Owner role
reporter access: the Reporter role
reporter permission: the Reporter role
reporter permissions: the Reporter role

View File

@ -10,7 +10,7 @@ type: reference, api
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.10.
> - The legacy key/value pair `{ "<date>" => "<value>" }` was removed from the payload in GitLab 14.0.
All methods require [reporter permissions and above](../../user/permissions.md).
All methods require at least the Reporter [role](../../user/permissions.md).
## Get project-level DORA metrics

View File

@ -27,7 +27,7 @@ You can even access a [web terminal](#web-terminals-deprecated) for your environ
Prerequisites:
- You must have a minimum of [Reporter permission](../../user/permissions.md#project-members-permissions).
- You must have at least the Reporter [role](../../user/permissions.md#project-members-permissions).
To view a list of environments and deployments:

View File

@ -102,10 +102,9 @@ The group now has access and can be seen in the UI.
## Environment access by group membership
A user may be granted access to protected environments as part of
[group membership](../../user/group/index.md). Users with
[Reporter permissions](../../user/permissions.md), can only be granted access to
protected environments with this method.
A user may be granted access to protected environments as part of [group membership](../../user/group/index.md). Users
with the Reporter [role](../../user/permissions.md) can only be granted access to protected environments with this
method.
## Deployment branch access
@ -126,8 +125,8 @@ they have the following privileges:
Users granted access to a protected environment, but not push or merge access
to the branch deployed to it, are only granted access to deploy the environment. An individual in a
group with the Reporter permission, or in groups added to the project with Reporter permissions,
appears in the dropdown menu for deployment-only access.
group with the Reporter [role](../../user/permissions.md), or in groups added to the project with the Reporter
role, appears in the dropdown menu for deployment-only access.
To add deployment-only access:
@ -136,7 +135,8 @@ To add deployment-only access:
1. Invite the group to be a project member.
1. Follow the steps in [Protecting Environments](#protecting-environments).
Note that deployment-only access is the only possible access level for groups with [Reporter permissions](../../user/permissions.md).
Note that deployment-only access is the only possible access level for groups with the Reporter
[role](../../user/permissions.md).
## Modifying and unprotecting environments

View File

@ -156,7 +156,7 @@ the GitLab instance. To determine this:
1. On the left sidebar, select **Overview > Runners**.
1. Find the runner in the table and view the **IP Address** column.
![shared runner IP address](img/shared_runner_ip_address_14_1.png)
![shared runner IP address](img/shared_runner_ip_address_14_5.png)
### Determine the IP address of a specific runner

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -111,7 +111,7 @@ Each line represents a rule that was evaluated. There are a few things to note:
Here you can see that the first four rules were evaluated `false` for
which user and subject. For example, you can see in the last line that
the rule was activated because the user `john` had Reporter access to
the rule was activated because the user `john` had the Reporter [role](../user/permissions.md) on
`Project/4`.
When a policy is asked whether a particular ability is allowed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -315,11 +315,11 @@ To search runners' descriptions:
You can also filter runners by status, type, and tag. To filter:
1. Click in the **Search or filter results...** field.
1. Select **Status**, **Type**, or **Tags**.
1. Select a tab or the **Search or filter results...** field.
1. Select any **Type**, or filter by **Status** or **Tags**.
1. Select or enter your search criteria.
![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_1.png)
![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_5.png)
For each runner, the following attributes are listed:

View File

@ -22,7 +22,7 @@ Initially, no data appears. Data is populated as users comment on open merge req
## Overview
Code Review Analytics is available to users with Reporter access and above, and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
Code Review Analytics is available to users with at least the Reporter [role](../permissions.md), and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
To access Code Review Analytics, from your project's menu, go to **Analytics > Code Review**.

View File

@ -116,4 +116,4 @@ bookmark for those preferred settings in your browser.
The **Merge Request Analytics** feature can be accessed only:
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
- By users with [Reporter access](../permissions.md) and above.
- By users with at least the Reporter [role](../permissions.md).

View File

@ -103,4 +103,4 @@ You can filter analytics based on a date range. To filter results:
The **Productivity Analytics** dashboard can be accessed only:
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
- By users with [Reporter access](../permissions.md) and above.
- By users with at least the Reporter [role](../permissions.md).

View File

@ -16,7 +16,7 @@ enabling you to see statistics about the resources that Terraform creates,
modifies, or destroys.
WARNING:
Like any other job artifact, Terraform Plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
Like any other job artifact, Terraform Plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform Plan
includes sensitive data such as passwords, access tokens, or certificates, we strongly
recommend encrypting plan output or modifying the project visibility settings.

View File

@ -205,7 +205,7 @@ and the CI YAML file:
The output from the above `terraform` commands should be viewable in the job logs.
WARNING:
Like any other job artifact, Terraform plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
Like any other job artifact, Terraform plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
recommends encrypting plan output or modifying the project visibility settings.

View File

@ -434,7 +434,7 @@ Be aware that this regex could lead to a
## Free Guest users **(ULTIMATE)**
When a user is given Guest permissions on a project, group, or both, and holds no
When a user is given the Guest role on a project, group, or both, and holds no
higher permission level on any other project or group on the GitLab instance,
the user is considered a guest user by GitLab and does not consume a license seat.
There is no other specific "guest" designation for newly created users.

View File

@ -594,7 +594,7 @@ You can move issues and lists by dragging them.
Prerequisites:
- A minimum of [Reporter](../permissions.md#project-members-permissions) access to a project in GitLab.
- You must have at least the Reporter [role](../permissions.md#project-members-permissions) for a project in GitLab.
To move an issue, select the issue card and drag it to another position in its current list or
into a different list. Learn about possible effects in [Dragging issues between lists](#dragging-issues-between-lists).

View File

@ -25,7 +25,7 @@ In an issue, leave a comment using the `/zoom` quick action followed by a valid
/zoom https://zoom.us/j/123456789
```
If the Zoom meeting URL is valid and you have at least [Reporter permissions](../../permissions.md),
If the Zoom meeting URL is valid and you have at least the Reporter [role](../../permissions.md),
a system alert notifies you of its successful addition.
The issue's description is automatically edited to include the Zoom link, and a button
appears right under the issue's title.
@ -44,5 +44,5 @@ Similarly to adding a Zoom meeting, you can remove it with a quick action:
/remove_zoom
```
If you have at least [Reporter permissions](../../permissions.md),
If you have at least the Reporter [role](../../permissions.md),
a system alert notifies you that the meeting URL was successfully removed.

View File

@ -77,14 +77,14 @@ that prevent leaks of private data.
There are two kinds of level access for confidential issues. The general rule
is that confidential issues are visible only to members of a project with at
least [Reporter access](../../permissions.md#project-members-permissions). However, a guest user can also create
least the Reporter [role](../../permissions.md#project-members-permissions). However, a guest user can also create
confidential issues, but can only view the ones that they created themselves.
Confidential issues are also hidden in search results for unprivileged users.
For example, here's what a user with the [Maintainer role](../../permissions.md) and Guest access
For example, here's what a user with the [Maintainer role](../../permissions.md) and the Guest role
sees in the project's search results respectively.
| Maintainer role | Guest access |
| Maintainer role | Guest role |
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Due dates **(FREE)**
Due dates can be used in [issues](index.md) to keep track of deadlines and make sure features are
shipped on time. Users need at least [Reporter permissions](../../permissions.md)
shipped on time. Users need at least the Reporter [role](../../permissions.md)
to be able to edit the due date. All users with permission to view
the issue can view the due date.

View File

@ -167,7 +167,7 @@ for protected branches. **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
> - Moved to GitLab Premium in 13.9.
You may need to grant users with [Reporter permissions](../../../permissions.md#project-members-permissions),
You may have to grant users with the Reporter [role](../../../permissions.md#project-members-permissions)
permission to approve merge requests before they can merge to a protected branch.
Some users (like managers) may not need permission to push or merge code, but still need
oversight on proposed work. To enable approval permissions for these users without

View File

@ -40,7 +40,7 @@ protected branch.
## Forking workflow
With the forking workflow, maintainers get the [Maintainer role](../../permissions.md) and regular
developers get Reporter access to the authoritative repository, which prohibits
developers get the Reporter role on the authoritative repository, which prohibits
them from pushing any changes to it.
Developers create forks of the authoritative project and push their feature

View File

@ -716,11 +716,11 @@ In the API:
### View a release and download assets
> [The Guest permission for read action was adjusted](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
> [Changes were made to the Guest role access](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
- Users with [Reporter role or above](../../../user/permissions.md#project-members-permissions)
- Users with the [Reporter role or above](../../../user/permissions.md#project-members-permissions)
have read and download access to the project releases.
- Users with [Guest role](../../../user/permissions.md#project-members-permissions)
- Users with the [Guest role](../../../user/permissions.md#project-members-permissions)
have read and download access to the project releases.
This includes associated Git-tag-names, release description, author information of the releases.
However, other repository-related information, such as [source code](#source-code), [release evidence](#release-evidence) are redacted.

View File

@ -101,7 +101,7 @@ module API
# of time after a Gitaly timeout, to mitigate frequent Gitaly timeouts
# for some Commit diffs.
def diff_files(commit)
return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project)
return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project, default_enabled: :yaml)
cache_key = [
GITALY_TIMEOUT_CACHE_KEY,

View File

@ -13811,7 +13811,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@ -23996,7 +23996,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"

View File

@ -44,6 +44,7 @@ User-Agent: *
Disallow: /groups/*/analytics
Disallow: /groups/*/contribution_analytics
Disallow: /groups/*/group_members
Disallow: /groups/*/-/saml/sso
# Project details
User-Agent: *

View File

@ -1,39 +0,0 @@
# frozen_string_literal: true
Gem::Specification.new do |s|
s.name = 'mygem'
s.authors = ['Tanuki Steve', 'Hal 9000']
s.author = 'Tanuki Steve'
s.version = '0.0.1'
s.date = '2011-09-29'
s.summary = 'package is the best'
s.files = ['lib/hello_gem.rb']
s.require_paths = ['lib']
s.description = 'A test package for GitLab.'
s.email = 'tanuki@not_real.com'
s.homepage = 'https://gitlab.com/ruby-co/my-package'
s.license = 'MIT'
s.metadata = {
'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
}
s.bindir = 'bin'
s.platform = Gem::Platform::RUBY
s.post_install_message = 'Installed, thank you!'
s.rdoc_options = ['--main']
s.required_ruby_version = '>= 2.7.0'
s.required_rubygems_version = '>= 1.8.11'
s.requirements = 'A high powered server or calculator'
s.rubygems_version = '1.8.09'
s.add_dependency 'dependency_1', '~> 1.2.3'
s.add_dependency 'dependency_2', '3.0.0'
s.add_dependency 'dependency_3', '>= 1.0.0'
s.add_dependency 'dependency_4'
end

View File

@ -5,15 +5,15 @@ module QA
module Project
module Registry
class Show < QA::Page::Base
view 'app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue' do
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue' do
element :registry_image_content
end
view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
element :more_actions_menu
end
view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
element :tag_delete_button
end

View File

@ -17,7 +17,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = 'conantest'
package.name = "conantest-#{SecureRandom.hex(8)}"
package.project = project
end
end

View File

@ -11,7 +11,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = "my_package"
package.name = "my_package-#{SecureRandom.hex(8)}"
package.project = project
end
end
@ -36,13 +36,13 @@ module QA
upload:
stage: upload
script:
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt'
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt'
tags:
- "runner-for-#{project.name}"
download:
stage: download
script:
- 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt -O file_downloaded.txt'
- 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt -O file_downloaded.txt'
tags:
- "runner-for-#{project.name}"
YAML

View File

@ -6,7 +6,7 @@ module QA
include Runtime::Fixtures
include_context 'packages registry qa scenario'
let(:package_name) { 'gitlab_qa_helm' }
let(:package_name) { "gitlab_qa_helm-#{SecureRandom.hex(8)}" }
let(:package_version) { '1.3.7' }
let(:package_type) { 'helm' }

View File

@ -8,7 +8,7 @@ module QA
include_context 'packages registry qa scenario'
let(:group_id) { 'com.gitlab.qa' }
let(:artifact_id) { 'maven_gradle' }
let(:artifact_id) { "maven_gradle-#{SecureRandom.hex(8)}" }
let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
let(:package_version) { '1.3.7' }
let(:package_type) { 'maven_gradle' }

View File

@ -125,7 +125,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = "@#{registry_scope}/#{project.name}"
package.name = "@#{registry_scope}/#{project.name}-#{SecureRandom.hex(8)}"
package.project = project
end
end

View File

@ -104,7 +104,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = "@#{registry_scope}/mypackage"
package.name = "@#{registry_scope}/mypackage-#{SecureRandom.hex(8)}"
package.project = project
end
end
@ -133,7 +133,7 @@ module QA
end
end
it "push and pull a npm package via CI using a #{params[:token_name]}", quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344537', type: :investigating } do
it "push and pull a npm package via CI using a #{params[:token_name]}" do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'

View File

@ -12,7 +12,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = 'mypypipackage'
package.name = "mypypipackage-#{SecureRandom.hex(8)}"
package.project = project
end
end
@ -57,7 +57,7 @@ module QA
install:
stage: install
script:
- "pip install mypypipackage --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
- "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
tags:
- "runner-for-#{project.name}"
@ -70,7 +70,7 @@ module QA
import setuptools
setuptools.setup(
name="mypypipackage",
name="#{package.name}",
version="0.0.1",
author="Example Author",
author_email="author@example.com",

View File

@ -13,7 +13,7 @@ module QA
let(:package) do
Resource::Package.init do |package|
package.name = 'mygem'
package.name = "mygem-#{SecureRandom.hex(8)}"
package.project = project
end
end
@ -46,17 +46,9 @@ module QA
it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1906' do
Flow::Login.sign_in
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.directory = Pathname
.new(__dir__)
.join('../../../../../fixtures/rubygems_package')
push.commit_message = 'RubyGems package'
end
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add mygem.gemspec'
commit.commit_message = 'Add package files'
commit.add_files(
[
{
@ -74,8 +66,8 @@ module QA
echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
- chmod 0600 ~/.gem/credentials
script:
- gem build mygem
- gem push mygem-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
- gem build #{package.name}
- gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
tags:
- "runner-for-#{project.name}"
YAML
@ -90,6 +82,52 @@ module QA
end
end
RUBY
},
{
file_path: "#{package.name}.gemspec",
content:
<<~RUBY
# frozen_string_literal: true
Gem::Specification.new do |s|
s.name = '#{package.name}'
s.authors = ['Tanuki Steve', 'Hal 9000']
s.author = 'Tanuki Steve'
s.version = '0.0.1'
s.date = '2011-09-29'
s.summary = 'this is a test package'
s.files = ['lib/hello_gem.rb']
s.require_paths = ['lib']
s.description = 'A test package for GitLab.'
s.email = 'tanuki@not_real.com'
s.homepage = 'https://gitlab.com/ruby-co/my-package'
s.license = 'MIT'
s.metadata = {
'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
}
s.bindir = 'bin'
s.platform = Gem::Platform::RUBY
s.post_install_message = 'Installed, thank you!'
s.rdoc_options = ['--main']
s.required_ruby_version = '>= 2.7.0'
s.required_rubygems_version = '>= 1.8.11'
s.requirements = 'A high powered server or calculator'
s.rubygems_version = '1.8.09'
s.add_dependency 'dependency_1', '~> 1.2.3'
s.add_dependency 'dependency_2', '3.0.0'
s.add_dependency 'dependency_3', '>= 1.0.0'
s.add_dependency 'dependency_4'
end
RUBY
}
]
)

View File

@ -0,0 +1,30 @@
import Frontmatter from '~/content_editor/extensions/frontmatter';
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
describe('content_editor/extensions/frontmatter', () => {
let tiptapEditor;
let doc;
let p;
beforeEach(() => {
tiptapEditor = createTestEditor({ extensions: [Frontmatter] });
({
builders: { doc, p },
} = createDocBuilder({
tiptapEditor,
names: {
frontmatter: { nodeType: Frontmatter.name },
},
}));
});
it('does not insert a frontmatter block when executing code block input rule', () => {
const expectedDoc = doc(p(''));
const inputRuleText = '``` ';
triggerNodeInputRule({ tiptapEditor, inputRuleText });
expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});

View File

@ -2,11 +2,11 @@
exports[`packages_list_app renders 1`] = `
<div>
<div
help-url="foo"
<infrastructure-title-stub
helpurl="foo"
/>
<div />
<infrastructure-search-stub />
<div>
<section

View File

@ -9,6 +9,7 @@ import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import * as packageUtils from '~/packages_and_registries/shared/utils';
import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
@ -26,18 +27,9 @@ describe('packages_list_app', () => {
};
const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
// we need to manually stub dynamic imported components because shallowMount is not able to stub them automatically. See: https://github.com/vuejs/vue-test-utils/issues/1279
const PackageSearch = { name: 'PackageSearch', template: '<div></div>' };
const PackageTitle = { name: 'PackageTitle', template: '<div></div>' };
const InfrastructureTitle = { name: 'InfrastructureTitle', template: '<div></div>' };
const InfrastructureSearch = { name: 'InfrastructureSearch', template: '<div></div>' };
const emptyListHelpUrl = 'helpUrl';
const findEmptyState = () => wrapper.find(GlEmptyState);
const findListComponent = () => wrapper.find(PackageList);
const findPackageSearch = () => wrapper.find(PackageSearch);
const findPackageTitle = () => wrapper.find(PackageTitle);
const findInfrastructureTitle = () => wrapper.find(InfrastructureTitle);
const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
const createStore = (filter = []) => {
@ -66,10 +58,6 @@ describe('packages_list_app', () => {
PackageList,
GlSprintf,
GlLink,
PackageSearch,
PackageTitle,
InfrastructureTitle,
InfrastructureSearch,
},
provide,
});
@ -191,48 +179,23 @@ describe('packages_list_app', () => {
});
});
describe('Package Search', () => {
describe('Search', () => {
it('exists', () => {
mountComponent();
expect(findPackageSearch().exists()).toBe(true);
expect(findInfrastructureSearch().exists()).toBe(true);
});
it('on update fetches data from the store', () => {
mountComponent();
store.dispatch.mockClear();
findPackageSearch().vm.$emit('update');
findInfrastructureSearch().vm.$emit('update');
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
});
});
describe('Infrastructure config', () => {
it('defaults to package registry components', () => {
mountComponent();
expect(findPackageSearch().exists()).toBe(true);
expect(findPackageTitle().exists()).toBe(true);
expect(findInfrastructureTitle().exists()).toBe(false);
expect(findInfrastructureSearch().exists()).toBe(false);
});
it('mount different component based on the provided values', () => {
mountComponent({
titleComponent: 'InfrastructureTitle',
searchComponent: 'InfrastructureSearch',
});
expect(findPackageSearch().exists()).toBe(false);
expect(findPackageTitle().exists()).toBe(false);
expect(findInfrastructureTitle().exists()).toBe(true);
expect(findInfrastructureSearch().exists()).toBe(true);
});
});
describe('delete alert handling', () => {
const originalLocation = window.location.href;
const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;

View File

@ -1,128 +0,0 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import component from '~/packages/list/components/package_search.vue';
import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
import { sortableFields } from '~/packages/list/utils';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Package Search', () => {
let wrapper;
let store;
const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
const findUrlSync = () => wrapper.findComponent(UrlSync);
const createStore = (isGroupPage) => {
const state = {
config: {
isGroupPage,
},
sorting: {
orderBy: 'version',
sort: 'desc',
},
filter: [],
};
store = new Vuex.Store({
state,
});
store.dispatch = jest.fn();
};
const mountComponent = (isGroupPage = false) => {
createStore(isGroupPage);
wrapper = shallowMount(component, {
localVue,
store,
stubs: {
UrlSync,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('has a registry search component', () => {
mountComponent();
expect(findRegistrySearch().exists()).toBe(true);
expect(findRegistrySearch().props()).toMatchObject({
filter: store.state.filter,
sorting: store.state.sorting,
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
sortableFields: sortableFields(),
});
});
it.each`
isGroupPage | page
${false} | ${'project'}
${true} | ${'group'}
`('in a $page page binds the right props', ({ isGroupPage }) => {
mountComponent(isGroupPage);
expect(findRegistrySearch().props()).toMatchObject({
filter: store.state.filter,
sorting: store.state.sorting,
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
sortableFields: sortableFields(isGroupPage),
});
});
it('on sorting:changed emits update event and calls vuex setSorting', () => {
const payload = { sort: 'foo' };
mountComponent();
findRegistrySearch().vm.$emit('sorting:changed', payload);
expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
expect(wrapper.emitted('update')).toEqual([[]]);
});
it('on filter:changed calls vuex setFilter', () => {
const payload = ['foo'];
mountComponent();
findRegistrySearch().vm.$emit('filter:changed', payload);
expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
});
it('on filter:submit emits update event', () => {
mountComponent();
findRegistrySearch().vm.$emit('filter:submit');
expect(wrapper.emitted('update')).toEqual([[]]);
});
it('has a UrlSync component', () => {
mountComponent();
expect(findUrlSync().exists()).toBe(true);
});
it('on query:changed calls updateQuery from UrlSync', () => {
jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
mountComponent();
findRegistrySearch().vm.$emit('query:changed');
expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
});
});

View File

@ -1,71 +0,0 @@
import { shallowMount } from '@vue/test-utils';
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list//constants';
import PackageTitle from '~/packages/list/components/package_title.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
describe('PackageTitle', () => {
let wrapper;
let store;
const findTitleArea = () => wrapper.find(TitleArea);
const findMetadataItem = () => wrapper.find(MetadataItem);
const mountComponent = (propsData = { helpUrl: 'foo' }) => {
wrapper = shallowMount(PackageTitle, {
store,
propsData,
stubs: {
TitleArea,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('title area', () => {
it('exists', () => {
mountComponent();
expect(findTitleArea().exists()).toBe(true);
});
it('has the correct props', () => {
mountComponent();
expect(findTitleArea().props()).toMatchObject({
title: LIST_TITLE_TEXT,
infoMessages: [{ text: LIST_INTRO_TEXT, link: 'foo' }],
});
});
});
describe.each`
count | exist | text
${null} | ${false} | ${''}
${undefined} | ${false} | ${''}
${0} | ${true} | ${'0 Packages'}
${1} | ${true} | ${'1 Package'}
${2} | ${true} | ${'2 Packages'}
`('when count is $count metadata item', ({ count, exist, text }) => {
beforeEach(() => {
mountComponent({ count, helpUrl: 'foo' });
});
it(`is ${exist} that it exists`, () => {
expect(findMetadataItem().exists()).toBe(exist);
});
if (exist) {
it('has the correct props', () => {
expect(findMetadataItem().props()).toMatchObject({
icon: 'package',
text,
});
});
}
});
});

View File

@ -1,48 +0,0 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import component from '~/packages/list/components/tokens/package_type_token.vue';
import { PACKAGE_TYPES } from '~/packages/list/constants';
describe('packages_filter', () => {
let wrapper;
const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
const findFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
const mountComponent = ({ attrs, listeners } = {}) => {
wrapper = shallowMount(component, {
attrs,
listeners,
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('it binds all of his attrs to filtered search token', () => {
mountComponent({ attrs: { foo: 'bar' } });
expect(findFilteredSearchToken().attributes('foo')).toBe('bar');
});
it('it binds all of his events to filtered search token', () => {
const clickListener = jest.fn();
mountComponent({ listeners: { click: clickListener } });
findFilteredSearchToken().vm.$emit('click');
expect(clickListener).toHaveBeenCalled();
});
it.each(PACKAGE_TYPES.map((p, index) => [p, index]))(
'displays a suggestion for %p',
(packageType, index) => {
mountComponent();
const item = findFilteredSearchSuggestions().at(index);
expect(item.text()).toBe(packageType.title);
expect(item.props('value')).toBe(packageType.type);
},
);
});

Some files were not shown because too many files have changed in this diff Show More