Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
226c5810c9
commit
a9f214d421
18 changed files with 198 additions and 22 deletions
|
@ -117,6 +117,7 @@ export default {
|
||||||
'autocompleteAwardEmojisPath',
|
'autocompleteAwardEmojisPath',
|
||||||
'calendarPath',
|
'calendarPath',
|
||||||
'canBulkUpdate',
|
'canBulkUpdate',
|
||||||
|
'canCreateProjects',
|
||||||
'canReadCrmContact',
|
'canReadCrmContact',
|
||||||
'canReadCrmOrganization',
|
'canReadCrmOrganization',
|
||||||
'emptyStateSvgPath',
|
'emptyStateSvgPath',
|
||||||
|
@ -136,6 +137,7 @@ export default {
|
||||||
'isSignedIn',
|
'isSignedIn',
|
||||||
'jiraIntegrationPath',
|
'jiraIntegrationPath',
|
||||||
'newIssuePath',
|
'newIssuePath',
|
||||||
|
'newProjectPath',
|
||||||
'releasesPath',
|
'releasesPath',
|
||||||
'rssPath',
|
'rssPath',
|
||||||
'showNewIssueLink',
|
'showNewIssueLink',
|
||||||
|
@ -844,12 +846,17 @@ export default {
|
||||||
</issuable-list>
|
</issuable-list>
|
||||||
|
|
||||||
<template v-else-if="isSignedIn">
|
<template v-else-if="isSignedIn">
|
||||||
<gl-empty-state
|
<gl-empty-state :title="$options.i18n.noIssuesSignedInTitle" :svg-path="emptyStateSvgPath">
|
||||||
:description="$options.i18n.noIssuesSignedInDescription"
|
<template #description>
|
||||||
:title="$options.i18n.noIssuesSignedInTitle"
|
<p>{{ $options.i18n.noIssuesSignedInDescription }}</p>
|
||||||
:svg-path="emptyStateSvgPath"
|
<p v-if="canCreateProjects">
|
||||||
>
|
<strong>{{ $options.i18n.noGroupIssuesSignedInDescription }}</strong>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
|
<gl-button v-if="canCreateProjects" :href="newProjectPath" variant="confirm">
|
||||||
|
{{ $options.i18n.newProjectLabel }}
|
||||||
|
</gl-button>
|
||||||
<gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
|
<gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
|
||||||
{{ $options.i18n.newIssueLabel }}
|
{{ $options.i18n.newIssueLabel }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
|
|
|
@ -29,7 +29,11 @@ export const i18n = {
|
||||||
jiraIntegrationSecondaryMessage: s__('JiraService|This feature requires a Premium plan.'),
|
jiraIntegrationSecondaryMessage: s__('JiraService|This feature requires a Premium plan.'),
|
||||||
jiraIntegrationTitle: s__('JiraService|Using Jira for issue tracking?'),
|
jiraIntegrationTitle: s__('JiraService|Using Jira for issue tracking?'),
|
||||||
newIssueLabel: __('New issue'),
|
newIssueLabel: __('New issue'),
|
||||||
|
newProjectLabel: __('New project'),
|
||||||
noClosedIssuesTitle: __('There are no closed issues'),
|
noClosedIssuesTitle: __('There are no closed issues'),
|
||||||
|
noGroupIssuesSignedInDescription: __(
|
||||||
|
'Issues exist in projects, so to create an issue, first create a project.',
|
||||||
|
),
|
||||||
noOpenIssuesDescription: __('To keep this project going, create a new issue'),
|
noOpenIssuesDescription: __('To keep this project going, create a new issue'),
|
||||||
noOpenIssuesTitle: __('There are no open issues'),
|
noOpenIssuesTitle: __('There are no open issues'),
|
||||||
noIssuesSignedInDescription: __(
|
noIssuesSignedInDescription: __(
|
||||||
|
|
|
@ -80,6 +80,7 @@ export function mountIssuesListApp() {
|
||||||
autocompleteAwardEmojisPath,
|
autocompleteAwardEmojisPath,
|
||||||
calendarPath,
|
calendarPath,
|
||||||
canBulkUpdate,
|
canBulkUpdate,
|
||||||
|
canCreateProjects,
|
||||||
canEdit,
|
canEdit,
|
||||||
canImportIssues,
|
canImportIssues,
|
||||||
canReadCrmContact,
|
canReadCrmContact,
|
||||||
|
@ -109,6 +110,7 @@ export function mountIssuesListApp() {
|
||||||
markdownHelpPath,
|
markdownHelpPath,
|
||||||
maxAttachmentSize,
|
maxAttachmentSize,
|
||||||
newIssuePath,
|
newIssuePath,
|
||||||
|
newProjectPath,
|
||||||
projectImportJiraPath,
|
projectImportJiraPath,
|
||||||
quickActionsHelpPath,
|
quickActionsHelpPath,
|
||||||
releasesPath,
|
releasesPath,
|
||||||
|
@ -133,6 +135,7 @@ export function mountIssuesListApp() {
|
||||||
autocompleteAwardEmojisPath,
|
autocompleteAwardEmojisPath,
|
||||||
calendarPath,
|
calendarPath,
|
||||||
canBulkUpdate: parseBoolean(canBulkUpdate),
|
canBulkUpdate: parseBoolean(canBulkUpdate),
|
||||||
|
canCreateProjects: parseBoolean(canCreateProjects),
|
||||||
canReadCrmContact: parseBoolean(canReadCrmContact),
|
canReadCrmContact: parseBoolean(canReadCrmContact),
|
||||||
canReadCrmOrganization: parseBoolean(canReadCrmOrganization),
|
canReadCrmOrganization: parseBoolean(canReadCrmOrganization),
|
||||||
emptyStateSvgPath,
|
emptyStateSvgPath,
|
||||||
|
@ -153,6 +156,7 @@ export function mountIssuesListApp() {
|
||||||
isSignedIn: parseBoolean(isSignedIn),
|
isSignedIn: parseBoolean(isSignedIn),
|
||||||
jiraIntegrationPath,
|
jiraIntegrationPath,
|
||||||
newIssuePath,
|
newIssuePath,
|
||||||
|
newProjectPath,
|
||||||
releasesPath,
|
releasesPath,
|
||||||
rssPath,
|
rssPath,
|
||||||
showNewIssueLink: parseBoolean(showNewIssueLink),
|
showNewIssueLink: parseBoolean(showNewIssueLink),
|
||||||
|
|
|
@ -238,10 +238,12 @@ module IssuesHelper
|
||||||
|
|
||||||
def group_issues_list_data(group, current_user)
|
def group_issues_list_data(group, current_user)
|
||||||
common_issues_list_data(group, current_user).merge(
|
common_issues_list_data(group, current_user).merge(
|
||||||
|
can_create_projects: can?(current_user, :create_projects, group).to_s,
|
||||||
can_read_crm_contact: can?(current_user, :read_crm_contact, group).to_s,
|
can_read_crm_contact: can?(current_user, :read_crm_contact, group).to_s,
|
||||||
can_read_crm_organization: can?(current_user, :read_crm_organization, group).to_s,
|
can_read_crm_organization: can?(current_user, :read_crm_organization, group).to_s,
|
||||||
has_any_issues: @has_issues.to_s,
|
has_any_issues: @has_issues.to_s,
|
||||||
has_any_projects: @has_projects.to_s
|
has_any_projects: @has_projects.to_s,
|
||||||
|
new_project_path: new_project_path(namespace_id: group.id)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,7 @@ class DiffFileEntity < DiffFileBaseEntity
|
||||||
|
|
||||||
# Used for inline diffs
|
# Used for inline diffs
|
||||||
expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options) && diff_file.text? } do |diff_file|
|
expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options) && diff_file.text? } do |diff_file|
|
||||||
file = conflict_file(options, diff_file) || diff_file
|
highlighted_diff_lines_for(diff_file, options)
|
||||||
file.diff_lines_for_serializer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
expose :is_fully_expanded do |diff_file|
|
expose :is_fully_expanded do |diff_file|
|
||||||
|
@ -89,6 +88,15 @@ class DiffFileEntity < DiffFileBaseEntity
|
||||||
# If nothing is present, inline will be the default.
|
# If nothing is present, inline will be the default.
|
||||||
options.fetch(:diff_view, :inline).to_sym
|
options.fetch(:diff_view, :inline).to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def highlighted_diff_lines_for(diff_file, options)
|
||||||
|
file = conflict_file(options, diff_file) || diff_file
|
||||||
|
|
||||||
|
file.diff_lines_for_serializer
|
||||||
|
rescue Gitlab::Git::Conflict::Parser::UnmergeableFile
|
||||||
|
# Fallback to diff_file as it means that conflict lines can't be parsed due to limit
|
||||||
|
diff_file.diff_lines_for_serializer
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DiffFileEntity.prepend_mod
|
DiffFileEntity.prepend_mod
|
||||||
|
|
|
@ -55,7 +55,10 @@ module AutoMerge
|
||||||
def available_for?(merge_request)
|
def available_for?(merge_request)
|
||||||
strong_memoize("available_for_#{merge_request.id}") do
|
strong_memoize("available_for_#{merge_request.id}") do
|
||||||
merge_request.can_be_merged_by?(current_user) &&
|
merge_request.can_be_merged_by?(current_user) &&
|
||||||
merge_request.mergeable_state?(skip_ci_check: true) &&
|
merge_request.open? &&
|
||||||
|
!merge_request.broken? &&
|
||||||
|
!merge_request.draft? &&
|
||||||
|
merge_request.mergeable_discussions_state? &&
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CleanupBackfillIntegrationsEnableSslVerification < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
MIGRATION = 'BackfillIntegrationsEnableSslVerification'
|
||||||
|
|
||||||
|
def up
|
||||||
|
finalize_background_migration(MIGRATION)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropTemporaryIndexForBackfillIntegrationsEnableSslVerification < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
INDEX_NAME = 'tmp_index_integrations_on_id_where_type_droneci_or_teamcity'
|
||||||
|
INDEX_CONDITION = "type_new IN ('Integrations::DroneCi', 'Integrations::Teamcity') " \
|
||||||
|
"AND encrypted_properties IS NOT NULL"
|
||||||
|
|
||||||
|
def up
|
||||||
|
remove_concurrent_index_by_name :integrations, INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# this index is used in 20220209121435_backfill_integrations_enable_ssl_verification
|
||||||
|
add_concurrent_index :integrations, :id, where: INDEX_CONDITION, name: INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
1
db/schema_migrations/20220525131557
Normal file
1
db/schema_migrations/20220525131557
Normal file
|
@ -0,0 +1 @@
|
||||||
|
fe0e9acc39c2408853ea3fc35574c553172ad381a5b6f243578f44ed77dc75f8
|
1
db/schema_migrations/20220525131624
Normal file
1
db/schema_migrations/20220525131624
Normal file
|
@ -0,0 +1 @@
|
||||||
|
f34c6e7b75d375342f5c88a9c7b98e15031a6dcdadf7e7dad862ef5f32a54e68
|
|
@ -29975,8 +29975,6 @@ CREATE INDEX tmp_index_for_null_project_namespace_id ON projects USING btree (id
|
||||||
|
|
||||||
CREATE INDEX tmp_index_for_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
|
CREATE INDEX tmp_index_for_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
|
||||||
|
|
||||||
CREATE INDEX tmp_index_integrations_on_id_where_type_droneci_or_teamcity ON integrations USING btree (id) WHERE ((type_new = ANY (ARRAY['Integrations::DroneCi'::text, 'Integrations::Teamcity'::text])) AND (encrypted_properties IS NOT NULL));
|
|
||||||
|
|
||||||
CREATE INDEX tmp_index_issues_on_issue_type_and_id ON issues USING btree (issue_type, id);
|
CREATE INDEX tmp_index_issues_on_issue_type_and_id ON issues USING btree (issue_type, id);
|
||||||
|
|
||||||
CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
|
CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
|
||||||
|
|
|
@ -175,6 +175,8 @@ To configure streaming audit events for Git operations, see [Add a new event str
|
||||||
|
|
||||||
### Headers
|
### Headers
|
||||||
|
|
||||||
|
> `X-Gitlab-Audit-Event-Type` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86881) in GitLab 15.0.
|
||||||
|
|
||||||
Headers are formatted as follows:
|
Headers are formatted as follows:
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
|
@ -182,6 +184,7 @@ POST /logs HTTP/1.1
|
||||||
Host: <DESTINATION_HOST>
|
Host: <DESTINATION_HOST>
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
|
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
|
||||||
|
X-Gitlab-Audit-Event-Type: repository_git_operation
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example payloads for SSH events
|
### Example payloads for SSH events
|
||||||
|
@ -212,7 +215,8 @@ Fetch:
|
||||||
"target_details": "example-project",
|
"target_details": "example-project",
|
||||||
"created_at": "2022-02-23T06:21:05.283Z",
|
"created_at": "2022-02-23T06:21:05.283Z",
|
||||||
"target_type": "Project",
|
"target_type": "Project",
|
||||||
"target_id": 29
|
"target_id": 29,
|
||||||
|
"event_type": "repository_git_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -242,7 +246,8 @@ Push:
|
||||||
"target_details": "example-project",
|
"target_details": "example-project",
|
||||||
"created_at": "2022-02-23T06:23:08.746Z",
|
"created_at": "2022-02-23T06:23:08.746Z",
|
||||||
"target_type": "Project",
|
"target_type": "Project",
|
||||||
"target_id": 29
|
"target_id": 29,
|
||||||
|
"event_type": "repository_git_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -274,7 +279,8 @@ Fetch:
|
||||||
"target_details": "example-project",
|
"target_details": "example-project",
|
||||||
"created_at": "2022-02-23T06:25:43.938Z",
|
"created_at": "2022-02-23T06:25:43.938Z",
|
||||||
"target_type": "Project",
|
"target_type": "Project",
|
||||||
"target_id": 29
|
"target_id": 29,
|
||||||
|
"event_type": "repository_git_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -304,7 +310,8 @@ Push:
|
||||||
"target_details": "example-project",
|
"target_details": "example-project",
|
||||||
"created_at": "2022-02-23T06:26:29.294Z",
|
"created_at": "2022-02-23T06:26:29.294Z",
|
||||||
"target_type": "Project",
|
"target_type": "Project",
|
||||||
"target_id": 29
|
"target_id": 29,
|
||||||
|
"event_type": "repository_git_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -333,7 +340,8 @@ Fetch:
|
||||||
"target_details": "example-group/example-project",
|
"target_details": "example-group/example-project",
|
||||||
"created_at": "2022-02-23T06:27:17.873Z",
|
"created_at": "2022-02-23T06:27:17.873Z",
|
||||||
"target_type": "Project",
|
"target_type": "Project",
|
||||||
"target_id": 29
|
"target_id": 29,
|
||||||
|
"event_type": "repository_git_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -352,6 +360,7 @@ POST /logs HTTP/1.1
|
||||||
Host: <DESTINATION_HOST>
|
Host: <DESTINATION_HOST>
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
|
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
|
||||||
|
X-Gitlab-Audit-Event-Type: audit_operation
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example payload
|
### Example payload
|
||||||
|
@ -377,6 +386,7 @@ X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
|
||||||
"target_details": "merge request title",
|
"target_details": "merge request title",
|
||||||
"created_at": "2022-03-09T06:53:11.181Z",
|
"created_at": "2022-03-09T06:53:11.181Z",
|
||||||
"target_type": "MergeRequest",
|
"target_type": "MergeRequest",
|
||||||
"target_id": 20
|
"target_id": 20,
|
||||||
|
"event_type": "audit_operation"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -21324,6 +21324,9 @@ msgstr ""
|
||||||
msgid "Issues closed"
|
msgid "Issues closed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Issues exist in projects, so to create an issue, first create a project."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Issues must match this scope to appear in this list."
|
msgid "Issues must match this scope to appear in this list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Create' do
|
RSpec.describe 'Create', quarantine: {
|
||||||
|
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/363807',
|
||||||
|
type: :stale
|
||||||
|
} do
|
||||||
describe 'Create a new merge request' do
|
describe 'Create a new merge request' do
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
|
|
|
@ -67,6 +67,7 @@ describe('CE IssuesListApp component', () => {
|
||||||
autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path',
|
autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path',
|
||||||
calendarPath: 'calendar/path',
|
calendarPath: 'calendar/path',
|
||||||
canBulkUpdate: false,
|
canBulkUpdate: false,
|
||||||
|
canCreateProjects: false,
|
||||||
canReadCrmContact: false,
|
canReadCrmContact: false,
|
||||||
canReadCrmOrganization: false,
|
canReadCrmOrganization: false,
|
||||||
emptyStateSvgPath: 'empty-state.svg',
|
emptyStateSvgPath: 'empty-state.svg',
|
||||||
|
@ -88,6 +89,7 @@ describe('CE IssuesListApp component', () => {
|
||||||
isSignedIn: true,
|
isSignedIn: true,
|
||||||
jiraIntegrationPath: 'jira/integration/path',
|
jiraIntegrationPath: 'jira/integration/path',
|
||||||
newIssuePath: 'new/issue/path',
|
newIssuePath: 'new/issue/path',
|
||||||
|
newProjectPath: 'new/project/path',
|
||||||
releasesPath: 'releases/path',
|
releasesPath: 'releases/path',
|
||||||
rssPath: 'rss/path',
|
rssPath: 'rss/path',
|
||||||
showNewIssueLink: true,
|
showNewIssueLink: true,
|
||||||
|
@ -118,6 +120,7 @@ describe('CE IssuesListApp component', () => {
|
||||||
issuesQueryResponse = jest.fn().mockResolvedValue(defaultQueryResponse),
|
issuesQueryResponse = jest.fn().mockResolvedValue(defaultQueryResponse),
|
||||||
issuesCountsQueryResponse = jest.fn().mockResolvedValue(getIssuesCountsQueryResponse),
|
issuesCountsQueryResponse = jest.fn().mockResolvedValue(getIssuesCountsQueryResponse),
|
||||||
sortPreferenceMutationResponse = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse),
|
sortPreferenceMutationResponse = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse),
|
||||||
|
stubs = {},
|
||||||
mountFn = shallowMount,
|
mountFn = shallowMount,
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
const requestHandlers = [
|
const requestHandlers = [
|
||||||
|
@ -136,6 +139,7 @@ describe('CE IssuesListApp component', () => {
|
||||||
data() {
|
data() {
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
stubs,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -521,10 +525,12 @@ describe('CE IssuesListApp component', () => {
|
||||||
|
|
||||||
it('shows empty state', () => {
|
it('shows empty state', () => {
|
||||||
expect(findGlEmptyState().props()).toMatchObject({
|
expect(findGlEmptyState().props()).toMatchObject({
|
||||||
description: IssuesListApp.i18n.noIssuesSignedInDescription,
|
|
||||||
title: IssuesListApp.i18n.noIssuesSignedInTitle,
|
title: IssuesListApp.i18n.noIssuesSignedInTitle,
|
||||||
svgPath: defaultProvide.emptyStateSvgPath,
|
svgPath: defaultProvide.emptyStateSvgPath,
|
||||||
});
|
});
|
||||||
|
expect(findGlEmptyState().text()).toContain(
|
||||||
|
IssuesListApp.i18n.noIssuesSignedInDescription,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows "New issue" and import/export buttons', () => {
|
it('shows "New issue" and import/export buttons', () => {
|
||||||
|
@ -538,11 +544,11 @@ describe('CE IssuesListApp component', () => {
|
||||||
|
|
||||||
it('shows Jira integration information', () => {
|
it('shows Jira integration information', () => {
|
||||||
const paragraphs = wrapper.findAll('p');
|
const paragraphs = wrapper.findAll('p');
|
||||||
expect(paragraphs.at(1).text()).toContain(IssuesListApp.i18n.jiraIntegrationTitle);
|
expect(paragraphs.at(2).text()).toContain(IssuesListApp.i18n.jiraIntegrationTitle);
|
||||||
expect(paragraphs.at(2).text()).toContain(
|
expect(paragraphs.at(3).text()).toContain(
|
||||||
'Enable the Jira integration to view your Jira issues in GitLab.',
|
'Enable the Jira integration to view your Jira issues in GitLab.',
|
||||||
);
|
);
|
||||||
expect(paragraphs.at(3).text()).toContain(
|
expect(paragraphs.at(4).text()).toContain(
|
||||||
IssuesListApp.i18n.jiraIntegrationSecondaryMessage,
|
IssuesListApp.i18n.jiraIntegrationSecondaryMessage,
|
||||||
);
|
);
|
||||||
expect(findGlLink().text()).toBe('Enable the Jira integration');
|
expect(findGlLink().text()).toBe('Enable the Jira integration');
|
||||||
|
@ -550,6 +556,29 @@ describe('CE IssuesListApp component', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when user is logged in and can create projects', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountComponent({
|
||||||
|
provide: { canCreateProjects: true, hasAnyIssues: false, isSignedIn: true },
|
||||||
|
stubs: { GlEmptyState },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows empty state with additional description about creating projects', () => {
|
||||||
|
expect(findGlEmptyState().text()).toContain(
|
||||||
|
IssuesListApp.i18n.noIssuesSignedInDescription,
|
||||||
|
);
|
||||||
|
expect(findGlEmptyState().text()).toContain(
|
||||||
|
IssuesListApp.i18n.noGroupIssuesSignedInDescription,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows "New project" button', () => {
|
||||||
|
expect(findGlButton().text()).toBe(IssuesListApp.i18n.newProjectLabel);
|
||||||
|
expect(findGlButton().attributes('href')).toBe(defaultProvide.newProjectPath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('when user is logged out', () => {
|
describe('when user is logged out', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = mountComponent({
|
wrapper = mountComponent({
|
||||||
|
|
|
@ -355,12 +355,14 @@ RSpec.describe IssuesHelper do
|
||||||
expected = {
|
expected = {
|
||||||
autocomplete_award_emojis_path: autocomplete_award_emojis_path,
|
autocomplete_award_emojis_path: autocomplete_award_emojis_path,
|
||||||
calendar_path: '#',
|
calendar_path: '#',
|
||||||
|
can_create_projects: 'true',
|
||||||
empty_state_svg_path: '#',
|
empty_state_svg_path: '#',
|
||||||
full_path: group.full_path,
|
full_path: group.full_path,
|
||||||
has_any_issues: false.to_s,
|
has_any_issues: false.to_s,
|
||||||
has_any_projects: true.to_s,
|
has_any_projects: true.to_s,
|
||||||
is_signed_in: current_user.present?.to_s,
|
is_signed_in: current_user.present?.to_s,
|
||||||
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
|
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
|
||||||
|
new_project_path: new_project_path(namespace_id: group.id),
|
||||||
rss_path: '#',
|
rss_path: '#',
|
||||||
sign_in_path: new_user_session_path
|
sign_in_path: new_user_session_path
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration!
|
||||||
|
|
||||||
|
RSpec.describe CleanupBackfillIntegrationsEnableSslVerification, :migration do
|
||||||
|
let(:job_class_name) { 'BackfillIntegrationsEnableSslVerification' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
# Jobs enqueued in Sidekiq.
|
||||||
|
Sidekiq::Testing.disable! do
|
||||||
|
BackgroundMigrationWorker.perform_in(10, job_class_name, [1, 2])
|
||||||
|
BackgroundMigrationWorker.perform_in(20, job_class_name, [3, 4])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Jobs tracked in the database.
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: job_class_name,
|
||||||
|
arguments: [5, 6],
|
||||||
|
status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
|
||||||
|
)
|
||||||
|
Gitlab::Database::BackgroundMigrationJob.create!(
|
||||||
|
class_name: job_class_name,
|
||||||
|
arguments: [7, 8],
|
||||||
|
status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
|
||||||
|
)
|
||||||
|
|
||||||
|
migrate!
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like(
|
||||||
|
'finalized tracked background migration',
|
||||||
|
Gitlab::BackgroundMigration::BackfillIntegrationsEnableSslVerification
|
||||||
|
)
|
||||||
|
end
|
|
@ -91,5 +91,38 @@ RSpec.describe DiffFileEntity do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#highlighted_diff_lines' do
|
||||||
|
context 'file without a conflict' do
|
||||||
|
let(:options) { { conflicts: {} } }
|
||||||
|
|
||||||
|
it 'calls diff_lines_for_serializer on diff_file' do
|
||||||
|
# #diff_lines_for_serializer gets called in #fully_expanded? as well so we expect twice
|
||||||
|
expect(diff_file).to receive(:diff_lines_for_serializer).twice.and_return([])
|
||||||
|
expect(subject[:highlighted_diff_lines]).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'file with a conflict' do
|
||||||
|
let(:conflict_file) { instance_double(Gitlab::Conflict::File, conflict_type: :both_modified) }
|
||||||
|
let(:options) { { conflicts: { diff_file.new_path => conflict_file } } }
|
||||||
|
|
||||||
|
it 'calls diff_lines_for_serializer on matching conflict file' do
|
||||||
|
expect(conflict_file).to receive(:diff_lines_for_serializer).and_return([])
|
||||||
|
expect(subject[:highlighted_diff_lines]).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when Gitlab::Git::Conflict::Parser::UnmergeableFile gets raised' do
|
||||||
|
before do
|
||||||
|
allow(conflict_file).to receive(:diff_lines_for_serializer).and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'falls back to diff_file diff_lines_for_serializer' do
|
||||||
|
expect(diff_file).to receive(:diff_lines_for_serializer).and_return([])
|
||||||
|
expect(subject[:highlighted_diff_lines]).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'diff file with conflict_type'
|
it_behaves_like 'diff file with conflict_type'
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue