Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-29 12:09:26 +00:00
parent 3fdeaff80e
commit f167d24074
26 changed files with 203 additions and 200 deletions

View File

@ -6,6 +6,7 @@ import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
import { escape } from 'lodash';
import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import rollbackEnvironment from '../graphql/mutations/rollback_environment.mutation.graphql';
import eventHub from '../event_hub';
@ -84,7 +85,9 @@ export default {
return this.environment.commitUrl;
},
modalActionText() {
return this.isLastDeployment ? s__('Environments|Re-deploy') : s__('Environments|Rollback');
return this.isLastDeployment
? s__('Environments|Re-deploy environment')
: s__('Environments|Rollback environment');
},
primaryProps() {
let attributes = [{ variant: 'danger' }];
@ -101,6 +104,15 @@ export default {
isLastDeployment() {
return this.environment?.isLastDeployment || this.environment?.lastDeployment?.isLast;
},
modalBodyText() {
return this.isLastDeployment
? s__(
'Environments|This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?',
)
: s__(
'Environments|This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?',
);
},
},
methods: {
handleChange(event) {
@ -125,6 +137,7 @@ export default {
text: __('Cancel'),
attributes: [{ variant: 'danger' }],
},
docsPath: helpPagePath('ci/environments/index.md', { anchor: 'retry-or-roll-back-a-deployment' }),
};
</script>
<template>
@ -137,33 +150,14 @@ export default {
@ok="onOk"
@change="handleChange"
>
<gl-sprintf
v-if="environment.isLastDeployment"
:message="
s__(
'Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?',
)
"
>
<template #link>
<gl-sprintf :message="modalBodyText">
<template #commitId>
<gl-link :href="commitUrl" target="_blank" class="commit-sha mr-0">{{
commitShortSha
}}</gl-link>
</template>
</gl-sprintf>
<gl-sprintf
v-else
:message="
s__(
'Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?',
)
"
>
<template #name>{{ environment.name }}</template>
<template #link>
<gl-link :href="commitUrl" target="_blank" class="commit-sha mr-0">{{
commitShortSha
}}</gl-link>
<template #docs="{ content }">
<gl-link :href="$options.docsLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-modal>

View File

@ -1,13 +1,20 @@
<script>
import { GlButton, GlIcon } from '@gitlab/ui';
import { GlButton, GlLink, GlSprintf } from '@gitlab/ui';
import { uniqBy } from 'lodash';
import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
export default {
i18n: {
collapseReplies: s__('Notes|Collapse replies'),
expandReplies: s__('Notes|Expand replies'),
lastReplyBy: s__('Notes|Last reply by %{name}'),
},
components: {
GlButton,
GlIcon,
GlLink,
GlSprintf,
UserAvatarLink,
TimeAgoTooltip,
},
@ -28,63 +35,83 @@ export default {
uniqueAuthors() {
const authors = this.replies.map((reply) => reply.author || {});
return uniqBy(authors, (author) => author.username);
return uniqBy(authors, 'username');
},
className() {
return this.collapsed ? 'collapsed' : 'expanded';
liClasses() {
return this.collapsed
? 'gl-text-gray-500 gl-rounded-bottom-left-base gl-rounded-bottom-right-base'
: 'gl-border-b';
},
buttonIcon() {
return this.collapsed ? 'chevron-right' : 'chevron-down';
},
buttonLabel() {
return this.collapsed ? this.$options.i18n.expandReplies : this.$options.i18n.collapseReplies;
},
},
methods: {
toggle() {
this.$refs.toggle.$el.focus();
this.$emit('toggle');
},
},
ICON_CLASS: 'gl-mr-3 gl-cursor-pointer',
};
</script>
<template>
<li
:class="className"
class="replies-toggle js-toggle-replies gl-display-flex! gl-align-items-center gl-flex-wrap"
:class="liClasses"
class="gl-display-flex! gl-align-items-center gl-flex-wrap gl-bg-gray-10 gl-py-3 gl-px-5 gl-border-t"
>
<gl-button
ref="toggle"
class="gl-my-2 gl-mr-3 gl-p-0!"
category="tertiary"
:icon="buttonIcon"
:aria-label="buttonLabel"
@click="toggle"
/>
<template v-if="collapsed">
<gl-icon :class="$options.ICON_CLASS" name="chevron-right" @click.native="toggle" />
<div>
<user-avatar-link
v-for="author in uniqueAuthors"
:key="author.username"
:link-href="author.path"
:img-alt="author.name"
:img-src="author.avatar_url"
:img-size="24"
:tooltip-text="author.name"
tooltip-placement="bottom"
/>
</div>
<user-avatar-link
v-for="author in uniqueAuthors"
:key="author.username"
class="gl-mr-3"
:link-href="author.path"
:img-alt="author.name"
img-css-classes="gl-mr-0!"
:img-src="author.avatar_url"
:img-size="24"
:tooltip-text="author.name"
tooltip-placement="bottom"
/>
<gl-button
class="js-replies-text gl-mr-2"
category="tertiary"
class="gl-mr-2"
variant="link"
data-qa-selector="expand_replies_button"
@click="toggle"
>
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
{{ n__('%d reply', '%d replies', replies.length) }}
</gl-button>
{{ __('Last reply by') }}
<a :href="lastReply.author.path" class="btn btn-link author-link gl-mx-2 gl-button">
{{ lastReply.author.name }}
</a>
<gl-sprintf :message="$options.i18n.lastReplyBy">
<template #name>
<gl-link
:href="lastReply.author.path"
class="gl-text-body! gl-text-decoration-none! gl-mx-2"
>
{{ lastReply.author.name }}
</gl-link>
</template>
</gl-sprintf>
<time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />
</template>
<div
<gl-button
v-else
class="collapse-replies-btn js-collapse-replies gl-display-flex align-items-center"
class="gl-text-body! gl-text-decoration-none!"
variant="link"
data-qa-selector="collapse_replies_button"
@click="toggle"
>
<gl-icon :class="$options.ICON_CLASS" name="chevron-down" />
<span class="gl-cursor-pointer">{{ s__('Notes|Collapse replies') }}</span>
</div>
{{ $options.i18n.collapseReplies }}
</gl-button>
</li>
</template>

View File

@ -67,6 +67,7 @@
}
.user-avatar-link {
display: flow-root;
text-decoration: none;
}

View File

@ -70,41 +70,6 @@ $system-note-svg-size: 16px;
}
}
.replies-toggle {
background-color: $gray-light;
padding: $gl-padding-8 $gl-padding;
border-top: 1px solid $gray-100;
border-bottom: 1px solid $gray-100;
.collapse-replies-btn:hover {
color: $blue-600;
}
&.collapsed {
color: $gl-text-color-secondary;
border-radius: 0 0 $border-radius-default $border-radius-default;
img {
margin: -2px 4px 0 0;
}
.author-link {
color: $gl-text-color;
}
}
.user-avatar-link {
&:last-child img {
margin-right: $gl-padding-8;
}
}
.btn-link {
border: 0;
vertical-align: baseline;
}
}
.discussion-toggle-replies {
border-top: 0;
border-radius: 4px 4px 0 0;

View File

@ -17,7 +17,7 @@ class Import::FogbugzController < Import::BaseController
res = Gitlab::FogbugzImport::Client.new(import_params.to_h.symbolize_keys)
rescue StandardError
# If the URI is invalid various errors can occur
return redirect_to new_import_fogbugz_path, alert: _('Could not connect to FogBugz, check your URL')
return redirect_to new_import_fogbugz_path(namespace_id: params[:namespace_id]), alert: _('Could not connect to FogBugz, check your URL')
end
session[:fogbugz_token] = res.get_token
session[:fogbugz_uri] = params[:uri]

View File

@ -321,5 +321,3 @@ class CommitStatus < Ci::ApplicationRecord
script_failure? || missing_dependency_failure? || archived_failure? || scheduler_failure? || data_integrity_failure?
end
end
CommitStatus.prepend_mod_with('CommitStatus')

View File

@ -29,9 +29,12 @@ module Enums
builds_disabled: 20,
environment_creation_failure: 21,
deployment_rejected: 22,
protected_environment_failure: 1_000,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
upstream_bridge_project_not_found: 1_004,
insufficient_upstream_permissions: 1_005,
bridge_pipeline_is_child_pipeline: 1_006, # not used anymore, but cannot be deleted because of old data
downstream_pipeline_creation_failed: 1_007,
secrets_provider_not_found: 1_008,
@ -41,5 +44,3 @@ module Enums
end
end
end
Enums::Ci::CommitStatus.prepend_mod_with('Enums::Ci::CommitStatus')

View File

@ -16,8 +16,11 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
data_integrity_failure: 'There has been a structural integrity problem detected, please contact system administrator',
forward_deployment_failure: 'The deployment job is older than the previously succeeded deployment job, and therefore cannot be run',
pipeline_loop_detected: 'This job could not be executed because it would create infinitely looping pipelines',
insufficient_upstream_permissions: 'This job could not be executed because of insufficient permissions to track the upstream project.',
upstream_bridge_project_not_found: 'This job could not be executed because upstream bridge project could not be found.',
invalid_bridge_trigger: 'This job could not be executed because downstream pipeline trigger definition is invalid',
downstream_bridge_project_not_found: 'This job could not be executed because downstream bridge project could not be found',
protected_environment_failure: 'The environment this job is deploying to is protected. Only users with permission may successfully run this job.',
insufficient_bridge_permissions: 'This job could not be executed because of insufficient permissions to create a downstream pipeline',
bridge_pipeline_is_child_pipeline: 'This job belongs to a child pipeline and cannot create further child pipelines',
downstream_pipeline_creation_failed: 'The downstream pipeline could not be created',
@ -61,5 +64,3 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
ActionController::Base.helpers.link_to('How do I fix it?', help_page_path(path, anchor: anchor))
end
end
CommitStatusPresenter.prepend_mod_with('CommitStatusPresenter')

View File

@ -1,6 +1,5 @@
- if bizible_enabled?
<!-- Bizible -->
= javascript_include_tag "https://cdn.bizible.com/scripts/bizible.js"
= javascript_tag nonce: content_security_policy_nonce do
:plain
const bizibleScript = document.createElement('script');

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346257
milestone: '14.6'
type: development
group: group::source code
default_enabled: false
default_enabled: true

View File

@ -27,9 +27,9 @@ alternatives to server hooks include:
[Geo](geo/index.md) doesn't replicate server hooks to secondary nodes.
## Create a server hook for a single repository
## Create server hooks for a repository
To create a server hook for a single repository:
To create server hooks for a repository:
1. On the top bar, select **Menu > Admin**.
1. Go to **Overview > Projects** and select the project you want to add a server hook to.
@ -41,16 +41,21 @@ To create a server hook for a single repository:
- For Omnibus GitLab installations, the path is usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
- For an installation from source, the path is usually `/home/git/repositories/<group>/<project>.git`.
1. On the file system, create a new directory in the correct location called `custom_hooks`.
1. In the new `custom_hooks` directory, create a file with a name that matches the hook type. For example, for a
`pre-receive` server hook, the filename should be `pre-receive` with no extension.
1. Make the server hook file executable and ensure that it's owned by the Git user.
1. In the new `custom_hooks` directory:
- To create a single server hook, create a file with a name that matches the hook type. For example, for a
`pre-receive` server hook, the filename should be `pre-receive` with no extension.
- To create many server hooks, create a directory for the hooks that matches the hook type. For example, for a
`pre-receive` server hook, the directory name should be `pre-receive.d`. Put the files for the hook in that directory.
1. Make the server hook files executable and ensure that they are owned by the Git user.
1. Write the code to make the server hook function as expected. Server hooks can be in any programming language. Ensure
the [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top reflects the language type. For
example, if the script is in Ruby the shebang is probably `#!/usr/bin/env ruby`.
1. Make the hook file executable, ensure that it's owned by the Git user, and ensure it does not match the backup file
pattern (`*~`).
If the server hook code is properly implemented, it should execute when the Git hook is next triggered.
## Create a global server hook for all repositories
## Create global server hooks for all repositories
To create a Git hook that applies to all repositories, set a global server hook. The default global server hook directory
is in the GitLab Shell directory. Any server hook added there applies to all repositories, including:
@ -80,8 +85,11 @@ To use a different directory for global server hooks, set `custom_hooks_dir` in
To create a global server hook for all repositories:
1. On the GitLab server, go to the configured global server hook directory.
1. Create a new directory in this location called `pre-receive.d`, `post-receive.d`, or `update.d`, depending on the type
of server hook. Any other names are ignored.
1. In the configured global server hook directory:
- To create a single server hook, create a file with a name that matches the hook type. For example, for a
`pre-receive` server hook, the filename should be `pre-receive` with no extension.
- To create many server hooks, create a directory for the hooks that matches the hook type. For example, for a
`pre-receive` server hook, the directory name should be `pre-receive.d`. Put the files for the hook in that directory.
1. Inside this new directory, add your server hook. Server hooks can be in any programming language. Ensure the
[shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top reflects the language type. For example, if the
script is in Ruby the shebang is probably `#!/usr/bin/env ruby`.

View File

@ -20,10 +20,13 @@ module Gitlab
scheduler_failure: 'scheduler failure',
data_integrity_failure: 'data integrity failure',
forward_deployment_failure: 'forward deployment failure',
protected_environment_failure: 'protected environment failure',
pipeline_loop_detected: 'job would create infinitely looping pipelines',
invalid_bridge_trigger: 'downstream pipeline trigger definition is invalid',
downstream_bridge_project_not_found: 'downstream project could not be found',
upstream_bridge_project_not_found: 'upstream project could not be found',
insufficient_bridge_permissions: 'no permissions to trigger downstream pipeline',
insufficient_upstream_permissions: 'no permissions to read upstream project',
bridge_pipeline_is_child_pipeline: 'creation of child pipeline not allowed from another child pipeline',
downstream_pipeline_creation_failed: 'downstream pipeline can not be created',
secrets_provider_not_found: 'secrets provider can not be found',
@ -74,5 +77,3 @@ module Gitlab
end
end
end
Gitlab::Ci::Status::Build::Failed.prepend_mod_with('Gitlab::Ci::Status::Build::Failed')

View File

@ -483,6 +483,8 @@ module Gitlab
raise Gitlab::Git::PreReceiveError.new(fallback_message: access_check_error.error_message)
when :cherry_pick_conflict
raise Gitlab::Git::Repository::CreateTreeError, 'CONFLICT'
when :changes_already_applied
raise Gitlab::Git::Repository::CreateTreeError, 'EMPTY'
when :target_branch_diverged
raise Gitlab::Git::CommitError, 'branch diverged'
else

View File

@ -363,6 +363,11 @@ msgid_plural "%d remaining"
msgstr[0] ""
msgstr[1] ""
msgid "%d reply"
msgid_plural "%d replies"
msgstr[0] ""
msgstr[1] ""
msgid "%d second"
msgid_plural "%d seconds"
msgstr[0] ""
@ -14555,7 +14560,7 @@ msgstr ""
msgid "Environments|Pod name"
msgstr ""
msgid "Environments|Re-deploy"
msgid "Environments|Re-deploy environment"
msgstr ""
msgid "Environments|Re-deploy environment %{name}?"
@ -14564,9 +14569,6 @@ msgstr ""
msgid "Environments|Re-deploy to environment"
msgstr ""
msgid "Environments|Rollback"
msgstr ""
msgid "Environments|Rollback environment"
msgstr ""
@ -14594,10 +14596,10 @@ msgstr ""
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
msgid "Environments|This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?"
msgstr ""
msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
msgid "Environments|This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?"
msgstr ""
msgid "Environments|Upcoming"
@ -26080,9 +26082,15 @@ msgstr ""
msgid "Notes|Collapse replies"
msgstr ""
msgid "Notes|Expand replies"
msgstr ""
msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
msgstr ""
msgid "Notes|Last reply by %{name}"
msgstr ""
msgid "Notes|Make this an internal note"
msgstr ""

View File

@ -29,12 +29,21 @@ RSpec.describe Import::FogbugzController do
expect(response).to redirect_to(new_user_map_import_fogbugz_path)
end
it 'preserves namespace_id query param' do
it 'preserves namespace_id query param on success' do
post :callback, params: { uri: uri, email: 'test@example.com', password: 'mypassword', namespace_id: namespace_id }
expect(response).to redirect_to(new_user_map_import_fogbugz_path(namespace_id: namespace_id))
end
it 'redirects to new page maintaining namespace_id when client raises standard error' do
namespace_id = 5
allow(::Gitlab::FogbugzImport::Client).to receive(:new).and_raise(StandardError)
post :callback, params: { uri: uri, email: 'test@example.com', password: 'mypassword', namespace_id: namespace_id }
expect(response).to redirect_to(new_import_fogbugz_url(namespace_id: namespace_id))
end
it 'redirects to new page form when client raises authentication exception' do
allow(::Gitlab::FogbugzImport::Client).to receive(:new).and_raise(::Fogbugz::AuthenticationException)

View File

@ -73,7 +73,7 @@ RSpec.describe 'Merge request > User scrolls to note on load', :js do
note_element = find(collapsed_fragment_id)
expect(note_element.visible?).to eq(true)
expect(note_element.sibling('.replies-toggle')[:class]).to include('expanded')
expect(note_element.sibling('li:nth-child(2)')).to have_button s_('Notes|Collapse replies')
end
end
end

View File

@ -2,6 +2,7 @@ import { GlModal, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { trimText } from 'helpers/text_helper';
import ConfirmRollbackModal from '~/environments/components/confirm_rollback_modal.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import eventHub from '~/environments/event_hub';
@ -76,9 +77,9 @@ describe('Confirm Rollback Modal Component', () => {
expect(modal.attributes('title')).toContain('Rollback');
expect(modal.attributes('title')).toContain('test');
expect(modal.props('actionPrimary').text).toBe('Rollback');
expect(modal.props('actionPrimary').text).toBe('Rollback environment');
expect(modal.props('actionPrimary').attributes).toEqual(primaryPropsAttrs);
expect(modal.text()).toContain('commit abc0123');
expect(trimText(modal.text())).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
});
@ -95,8 +96,8 @@ describe('Confirm Rollback Modal Component', () => {
expect(modal.attributes('title')).toContain('Re-deploy');
expect(modal.attributes('title')).toContain('test');
expect(modal.props('actionPrimary').text).toBe('Re-deploy');
expect(modal.text()).toContain('commit abc0123');
expect(modal.props('actionPrimary').text).toBe('Re-deploy environment');
expect(trimText(modal.text())).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
});
@ -156,7 +157,7 @@ describe('Confirm Rollback Modal Component', () => {
);
const modal = component.find(GlModal);
expect(modal.text()).toContain('commit abc0123');
expect(trimText(modal.text())).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
});
@ -180,7 +181,7 @@ describe('Confirm Rollback Modal Component', () => {
expect(modal.attributes('title')).toContain('Rollback');
expect(modal.attributes('title')).toContain('test');
expect(modal.props('actionPrimary').text).toBe('Rollback');
expect(modal.props('actionPrimary').text).toBe('Rollback environment');
expect(modal.props('actionPrimary').attributes).toEqual(primaryPropsAttrs);
});
@ -204,7 +205,7 @@ describe('Confirm Rollback Modal Component', () => {
expect(modal.attributes('title')).toContain('Re-deploy');
expect(modal.attributes('title')).toContain('test');
expect(modal.props('actionPrimary').text).toBe('Re-deploy');
expect(modal.props('actionPrimary').text).toBe('Re-deploy environment');
});
it('should commit the "rollback" mutation when "ok" is clicked', async () => {

View File

@ -1,13 +1,14 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ToggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { note } from '../mock_data';
const deepCloneObject = (obj) => JSON.parse(JSON.stringify(obj));
describe('toggle replies widget for notes', () => {
let vm;
let ToggleRepliesWidget;
let wrapper;
const deepCloneObject = (obj) => JSON.parse(JSON.stringify(obj));
const noteFromOtherUser = deepCloneObject(note);
noteFromOtherUser.author.username = 'fatihacet';
@ -17,62 +18,62 @@ describe('toggle replies widget for notes', () => {
const replies = [note, note, note, noteFromOtherUser, noteFromAnotherUser];
beforeEach(() => {
ToggleRepliesWidget = Vue.extend(toggleRepliesWidget);
});
const findCollapseToggleButton = () =>
wrapper.findByRole('button', { text: ToggleRepliesWidget.i18n.collapseReplies });
const findExpandToggleButton = () =>
wrapper.findByRole('button', { text: ToggleRepliesWidget.i18n.expandReplies });
const findRepliesButton = () => wrapper.findByRole('button', { text: '5 replies' });
const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip);
const findUserAvatarLink = () => wrapper.findAllComponents(UserAvatarLink);
const findUserLink = () => wrapper.findByRole('link', { text: noteFromAnotherUser.author.name });
const mountComponent = ({ collapsed = false }) =>
mountExtended(ToggleRepliesWidget, { propsData: { replies, collapsed } });
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('collapsed state', () => {
beforeEach(() => {
vm = mountComponent(ToggleRepliesWidget, {
replies,
collapsed: true,
});
wrapper = mountComponent({ collapsed: true });
});
it('should render the collapsed', () => {
const vmTextContent = vm.$el.textContent.replace(/\s\s+/g, ' ');
expect(vm.$el.classList.contains('collapsed')).toEqual(true);
expect(vm.$el.querySelectorAll('.user-avatar-link').length).toEqual(3);
expect(vm.$el.querySelector('time')).not.toBeNull();
expect(vmTextContent).toContain('5 replies');
expect(vmTextContent).toContain(`Last reply by ${noteFromAnotherUser.author.name}`);
it('renders collapsed state elements', () => {
expect(findExpandToggleButton().exists()).toBe(true);
expect(findUserAvatarLink()).toHaveLength(3);
expect(findRepliesButton().exists()).toBe(true);
expect(wrapper.text()).toContain('Last reply by');
expect(findUserLink().exists()).toBe(true);
expect(findTimeAgoTooltip().exists()).toBe(true);
});
it('should emit toggle event when the replies text clicked', () => {
const spy = jest.spyOn(vm, '$emit');
it('emits "toggle" event when expand toggle button is clicked', () => {
findExpandToggleButton().trigger('click');
vm.$el.querySelector('.js-replies-text').click();
expect(wrapper.emitted('toggle')).toEqual([[]]);
});
expect(spy).toHaveBeenCalledWith('toggle');
it('emits "toggle" event when replies button is clicked', () => {
findRepliesButton().trigger('click');
expect(wrapper.emitted('toggle')).toEqual([[]]);
});
});
describe('expanded state', () => {
beforeEach(() => {
vm = mountComponent(ToggleRepliesWidget, {
replies,
collapsed: false,
});
wrapper = mountComponent({ collapsed: false });
});
it('should render expanded state', () => {
const vmTextContent = vm.$el.textContent.replace(/\s\s+/g, ' ');
expect(vm.$el.querySelector('.collapse-replies-btn')).not.toBeNull();
expect(vmTextContent).toContain('Collapse replies');
it('renders expanded state elements', () => {
expect(findCollapseToggleButton().exists()).toBe(true);
});
it('should emit toggle event when the collapse replies text called', () => {
const spy = jest.spyOn(vm, '$emit');
it('emits "toggle" event when collapse toggle button is clicked', () => {
findCollapseToggleButton().trigger('click');
vm.$el.querySelector('.js-collapse-replies').click();
expect(spy).toHaveBeenCalledWith('toggle');
expect(wrapper.emitted('toggle')).toEqual([[]]);
});
});
});

View File

@ -193,8 +193,6 @@ RSpec.describe Gitlab::BareRepositoryImport::Importer, :seed_helper do
def prepare_repository(project_path, source_project)
repo_path = File.join(base_dir, project_path)
return create_bare_repository(repo_path) unless source_project
cmd = %W(#{Gitlab.config.git.bin_path} clone --bare #{source_project} #{repo_path})
system(git_env, *cmd, chdir: SEED_STORAGE_PATH, out: '/dev/null', err: '/dev/null')

View File

@ -59,18 +59,15 @@ RSpec.describe ::Gitlab::BareRepositoryImport::Repository do
let(:root_path) { TestEnv.repos_path }
let(:repo_path) { File.join(root_path, "#{hashed_path}.git") }
let(:wiki_path) { File.join(root_path, "#{hashed_path}.wiki.git") }
let(:raw_repository) { Gitlab::Git::Repository.new('default', "#{hashed_path}.git", nil, nil) }
before do
TestEnv.create_bare_repository(repo_path)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository = Rugged::Repository.new(repo_path)
repository.config['gitlab.fullpath'] = 'to/repo'
end
raw_repository.create_repository
raw_repository.set_full_path(full_path: 'to/repo')
end
after do
FileUtils.rm_rf(repo_path)
raw_repository.remove
end
subject { described_class.new(root_path, repo_path) }

View File

@ -543,15 +543,15 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context 'with legacy storage' do
let(:fake_repo_path) { File.join(TestEnv.repos_path, user.namespace.full_path, 'existing.git') }
let(:raw_fake_repo) { Gitlab::Git::Repository.new('default', File.join(user.namespace.full_path, 'existing.git'), nil, nil) }
before do
stub_application_setting(hashed_storage_enabled: false)
TestEnv.create_bare_repository(fake_repo_path)
raw_fake_repo.create_repository
end
after do
FileUtils.rm_rf(fake_repo_path)
raw_fake_repo.remove
end
it 'does not allow to create a project when path matches existing repository on disk' do
@ -578,15 +578,15 @@ RSpec.describe Projects::CreateService, '#execute' do
context 'with hashed storage' do
let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
let(:hashed_path) { '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
let(:fake_repo_path) { File.join(TestEnv.repos_path, "#{hashed_path}.git") }
let(:raw_fake_repo) { Gitlab::Git::Repository.new('default', "#{hashed_path}.git", nil, nil) }
before do
allow(Digest::SHA2).to receive(:hexdigest) { hash }
TestEnv.create_bare_repository(fake_repo_path)
raw_fake_repo.create_repository
end
after do
FileUtils.rm_rf(fake_repo_path)
raw_fake_repo.remove
end
it 'does not allow to create a project when path matches existing repository on disk' do

View File

@ -156,16 +156,16 @@ RSpec.describe Projects::ForkService do
end
context 'repository in legacy storage already exists' do
let(:fake_repo_path) { File.join(TestEnv.repos_path, @to_user.namespace.full_path, "#{@from_project.path}.git") }
let(:raw_fake_repo) { Gitlab::Git::Repository.new('default', File.join(@to_user.namespace.full_path, "#{@from_project.path}.git"), nil, nil) }
let(:params) { { namespace: @to_user.namespace, using_service: true } }
before do
stub_application_setting(hashed_storage_enabled: false)
TestEnv.create_bare_repository(fake_repo_path)
raw_fake_repo.create_repository
end
after do
FileUtils.rm_rf(fake_repo_path)
raw_fake_repo.remove
end
subject { fork_project(@from_project, @to_user, params) }

View File

@ -372,16 +372,16 @@ RSpec.describe Projects::TransferService do
end
context 'namespace which contains orphan repository with same projects path name' do
let(:fake_repo_path) { File.join(TestEnv.repos_path, group.full_path, "#{project.path}.git") }
let(:raw_fake_repo) { Gitlab::Git::Repository.new('default', File.join(group.full_path, "#{project.path}.git"), nil, nil) }
before do
group.add_owner(user)
TestEnv.create_bare_repository(fake_repo_path)
raw_fake_repo.create_repository
end
after do
FileUtils.rm_rf(fake_repo_path)
raw_fake_repo.remove
end
it 'does not allow the project transfer' do

View File

@ -348,17 +348,17 @@ RSpec.describe Projects::UpdateService do
end
context 'when renaming a project' do
let(:fake_repo_path) { File.join(TestEnv.repos_path, user.namespace.full_path, 'existing.git') }
let(:raw_fake_repo) { Gitlab::Git::Repository.new('default', File.join(user.namespace.full_path, 'existing.git'), nil, nil) }
context 'with legacy storage' do
let(:project) { create(:project, :legacy_storage, :repository, creator: user, namespace: user.namespace) }
before do
TestEnv.create_bare_repository(fake_repo_path)
raw_fake_repo.create_repository
end
after do
FileUtils.rm_rf(fake_repo_path)
raw_fake_repo.remove
end
it 'does not allow renaming when new path matches existing repository on disk' do

View File

@ -310,14 +310,6 @@ module TestEnv
end
end
def create_bare_repository(path)
FileUtils.mkdir_p(path)
system(git_env, *%W(#{Gitlab.config.git.bin_path} -C #{path} init --bare),
out: '/dev/null',
err: '/dev/null')
end
def repos_path
@repos_path ||= GitalySetup.repos_path
end

View File

@ -293,7 +293,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
it 'can be collapsed' do
submit_reply('another text')
find('.js-collapse-replies').click
click_button s_('Notes|Collapse replies'), match: :first
expect(page).to have_css('.discussion-notes .note', count: 1)
expect(page).to have_content '1 reply'
end