Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-07-22 09:09:38 +00:00
parent 6c7fe15312
commit c70359a07f
28 changed files with 308 additions and 98 deletions

View File

@ -1 +1 @@
906840b1edd8f8c17b6d1d4a7016b2ef0acf5b22
d758ff48fbf8392e08626b60685d037373347d72

View File

@ -530,6 +530,12 @@ const Api = {
return axios.get(url);
},
createRelease(projectPath, release) {
const url = Api.buildUrl(this.releasesPath).replace(':id', encodeURIComponent(projectPath));
return axios.post(url, release);
},
updateRelease(projectPath, tagName, release) {
const url = Api.buildUrl(this.releasePath)
.replace(':id', encodeURIComponent(projectPath))

View File

@ -87,11 +87,7 @@ export default {
<template>
<span>
<span ref="issueDueDate" :class="cssClass" class="board-card-info card-number">
<icon
:class="{ 'text-danger': isPastDue }"
class="board-card-info-icon align-top"
name="calendar"
/>
<icon :class="{ 'text-danger': isPastDue }" class="board-card-info-icon" name="calendar" />
<time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{
body
}}</time>

View File

@ -34,10 +34,9 @@ export default {
<template>
<span>
<span ref="issueTimeEstimate" class="board-card-info card-number">
<icon name="hourglass" class="board-card-info-icon align-top" /><time
class="board-card-info-text"
>{{ timeEstimate }}</time
>
<icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
timeEstimate
}}</time>
</span>
<gl-tooltip
:target="() => $refs.issueTimeEstimate"

View File

@ -1,12 +1,11 @@
/* eslint-disable no-underscore-dangle, class-methods-use-this */
import ListIssue from 'ee_else_ce/boards/models/issue';
import { __ } from '~/locale';
import ListLabel from './label';
import ListAssignee from './assignee';
import flash from '~/flash';
import boardsStore from '../stores/boards_store';
import ListMilestone from './milestone';
import 'ee_else_ce/boards/models/issue';
const TYPES = {
backlog: {
@ -100,12 +99,6 @@ class List {
return boardsStore.newListIssue(this, issue);
}
createIssues(data) {
data.forEach(issueObj => {
this.addIssue(new ListIssue(issueObj));
});
}
addMultipleIssues(issues, listFrom, newIndex) {
boardsStore.addMultipleListIssues(this, issues, listFrom, newIndex);
}

View File

@ -1,6 +1,6 @@
/* eslint-disable no-shadow, no-param-reassign,consistent-return */
/* global List */
/* global ListIssue */
import $ from 'jquery';
import { sortBy } from 'lodash';
import Vue from 'vue';
@ -641,7 +641,9 @@ const boardsStore = {
list.issues = [];
}
list.createIssues(data.issues);
data.issues.forEach(issueObj => {
list.addIssue(new ListIssue(issueObj));
});
return data;
});

View File

@ -1,11 +1,11 @@
<script>
import { __, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import { GlIcon } from '@gitlab/ui';
export default {
name: 'DesignNotePin',
components: {
Icon,
GlIcon,
},
props: {
position: {
@ -47,13 +47,13 @@ export default {
'btn-transparent comment-indicator': isNewNote,
'js-image-badge badge badge-pill': !isNewNote,
}"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0"
type="button"
@mousedown="$emit('mousedown', $event)"
@mouseup="$emit('mouseup', $event)"
@click="$emit('click', $event)"
>
<icon v-if="isNewNote" name="image-comment-dark" />
<gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
<template v-else>
{{ label }}
</template>

View File

@ -1,11 +1,11 @@
<script>
import { __, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import { GlIcon } from '@gitlab/ui';
export default {
name: 'DesignNotePin',
components: {
Icon,
GlIcon,
},
props: {
position: {
@ -47,13 +47,13 @@ export default {
'btn-transparent comment-indicator': isNewNote,
'js-image-badge badge badge-pill': !isNewNote,
}"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0"
type="button"
@mousedown="$emit('mousedown', $event)"
@mouseup="$emit('mouseup', $event)"
@click="$emit('click', $event)"
>
<icon v-if="isNewNote" name="image-comment-dark" />
<gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
<template v-else>
{{ label }}
</template>

View File

@ -521,7 +521,7 @@
}
&.board-card-weight {
color: $gl-text-color;
color: $gl-text-color-secondary;
cursor: pointer;
&:hover {
@ -531,8 +531,9 @@
}
.board-card-info-icon {
color: $gray-600;
color: $gray-700;
margin-right: $gl-padding-4;
vertical-align: text-top;
}
@include media-breakpoint-down(md) {

View File

@ -992,7 +992,8 @@ table.code {
}
.frame .badge.badge-pill,
.frame .image-comment-badge {
.frame .image-comment-badge,
.frame .comment-indicator {
// Center align badges on the frame
transform: translate(-50%, -50%);
}

View File

@ -271,7 +271,7 @@ module GitlabRoutingHelper
end
end
def gitlab_raw_snippet_blob_url(snippet, path, ref = nil)
def gitlab_raw_snippet_blob_url(snippet, path, ref = nil, **options)
params = {
snippet_id: snippet,
ref: ref || snippet.repository.root_ref,
@ -279,26 +279,14 @@ module GitlabRoutingHelper
}
if snippet.is_a?(ProjectSnippet)
project_snippet_blob_raw_url(snippet.project, params)
project_snippet_blob_raw_url(snippet.project, **params, **options)
else
snippet_blob_raw_url(params)
snippet_blob_raw_url(**params, **options)
end
end
def gitlab_raw_snippet_blob_path(blob, ref = nil)
snippet = blob.container
params = {
snippet_id: snippet,
ref: ref || blob.repository.root_ref,
path: blob.path
}
if snippet.is_a?(ProjectSnippet)
project_snippet_blob_raw_path(snippet.project, params)
else
snippet_blob_raw_path(params)
end
def gitlab_raw_snippet_blob_path(snippet, path, ref = nil, **options)
gitlab_raw_snippet_blob_url(snippet, path, ref, only_path: true, **options)
end
def gitlab_snippet_notes_path(snippet, *args)

View File

@ -17,7 +17,7 @@ class SnippetBlobPresenter < BlobPresenter
end
def raw_path
return gitlab_raw_snippet_blob_path(blob) if snippet_multiple_files?
return gitlab_raw_snippet_blob_path(snippet, blob.path) if snippet_multiple_files?
gitlab_raw_snippet_path(snippet)
end

View File

@ -1,6 +1,6 @@
%li.key-list-item
.float-left.gl-mr-3
= icon 'key', class: "settings-list-icon d-none d-sm-block"
= sprite_icon('key', size: 16, css_class: "settings-list-icon d-none d-sm-block gl-mt-4")
.key-list-item-info
- key.emails_with_verified_status.map do |email, verified|
= render partial: 'shared/email_with_badge', locals: { email: email, verified: verified }

View File

@ -1,7 +1,7 @@
- requirements_link_url = help_page_path('user/project/issues/design_management', anchor: 'requirements')
- requirements_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: requirements_link_url }
- link_end = '</a>'.html_safe
- enable_lfs_message = s_("DesignManagement|To upload designs, you'll need to %{requirements_link_start}enable LFS%{requirements_link_end}.").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end }
- enable_lfs_message = s_("DesignManagement|To upload designs, you'll need to enable LFS. %{requirements_link_start}More information%{requirements_link_end}").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end }
- if @project.design_management_enabled?
- if Feature.enabled?(:design_management_moved, @project, default_enabled: true)

View File

@ -0,0 +1,5 @@
---
title: Replace fa-key icon with svg
merge_request: 37251
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Remove createIssues logic from list model
merge_request: 32236
author: nuwe1
type: other

View File

@ -0,0 +1,5 @@
---
title: Fix sizing of pins for new design comments
merge_request: 37541
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix icon alignment on board cards
merge_request: 35710
author: carolcarvalhosa
type: fixed

View File

@ -212,6 +212,7 @@ application server, or a Gitaly node.
postgresql['enable'] = false
redis['enable'] = false
nginx['enable'] = false
alertmanager['enable'] = false
prometheus['enable'] = false
grafana['enable'] = false
puma['enable'] = false

View File

@ -11,6 +11,8 @@ last_update: 2019-07-03
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9186) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.0.
> - [Squash and merge](../../../../user/project/merge_requests/squash_and_merge.md) support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13001) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6.
For more information about why you might want to use Merge Trains, read [How merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
When [pipelines for merged results](../index.md#pipelines-for-merged-results-premium) are
enabled, the pipeline jobs run as if the changes from your source branch have already
been merged into the target branch.

View File

@ -145,6 +145,8 @@ build a matrix of targets and architectures.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM).
We also have an [example project using Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet) which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. You could use a similar process for other templating languages like [Dhall](https://dhall-lang.org/) or [`ytt`](https://get-ytt.io/).
In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail.
This is [resolved in GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/209070).

View File

@ -8,6 +8,7 @@ All template files reside in the `lib/gitlab/ci/templates` directory, and are ca
| Sub-directroy | Content | [Selectable in UI](#make-sure-the-new-template-can-be-selected-in-ui) |
|---------------|--------------------------------------------------------------|-----------------------------------------------------------------------|
| `/AWS/*` | Cloud Deployment (AWS) related jobs | No |
| `/Jobs/*` | Auto DevOps related jobs | Yes |
| `/Pages/*` | Static site generators for GitLab Pages (for example Jekyll) | Yes |
| `/Security/*` | Security related jobs | Yes |
@ -25,9 +26,37 @@ Also, all templates must be named with the `*.gitlab-ci.yml` suffix.
### Backward compatibility
A template might be dynamically included with the `include:template:` keyword. If
you make a change to an *existing* template, you must make sure that it won't break
you make a change to an *existing* template, you **must** make sure that it won't break
CI/CD in existing projects.
For example, changing a job name in a template could break pipelines in an existing project.
Let's say there is a template named `Performance.gitlab-ci.yml` with the following content:
```yaml
performance:
image: registry.gitlab.com/gitlab-org/verify-tools/performance:v0.1.0
script: ./performance-test $TARGET_URL
```
and users include this template with passing an argument to the `performance` job.
This can be done by specifying the environment variable `TARGET_URL` in _their_ `.gitlab-ci.yml`:
```yaml
include:
template: Performance.gitlab-ci.yml
performance:
variables:
TARGET_URL: https://awesome-app.com
```
If the job name `performance` in the template is renamed to `browser-performance`,
user's `.gitlab-ci.yml` will immediately cause a lint error because there
are no such jobs named `performance` in the included template anymore. Therefore,
users have to fix their `.gitlab-ci.yml` that could annoy their workflow.
Please read [versioning](#versioning) section for introducing breaking change safely.
## Testing
Each CI/CD template must be tested in order to make sure that it's safe to be published.
@ -64,3 +93,13 @@ You should write an RSpec test to make sure that pipeline jobs will be generated
A template could contain malicious code. For example, a template that contains the `export` shell command in a job
might accidentally expose project secret variables in a job log.
If you're unsure if it's secure or not, you need to ask security experts for cross-validation.
## Versioning
Versioning allows you to introduce a new template without modifying the existing
one. This is useful process especially when we need to introduce a breaking change,
but don't want to affect the existing projects that depends on the current template.
There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) for
introducing versioning concept in GitLab Ci Template. Please follow the issue for
checking the progress.

View File

@ -8192,7 +8192,7 @@ msgstr ""
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
msgid "DesignManagement|To upload designs, you'll need to %{requirements_link_start}enable LFS%{requirements_link_end}."
msgid "DesignManagement|To upload designs, you'll need to enable LFS. %{requirements_link_start}More information%{requirements_link_end}"
msgstr ""
msgid "DesignManagement|Unresolve thread"
@ -15537,6 +15537,9 @@ msgstr ""
msgid "NetworkPolicies|Name"
msgstr ""
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
@ -15549,6 +15552,12 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
msgid "NetworkPolicies|Policy description"
msgstr ""
msgid "NetworkPolicies|Policy editor"
msgstr ""
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr ""

View File

@ -644,6 +644,45 @@ RSpec.describe 'GFM autocomplete', :js do
expect(find('.tribute-container ul')).to have_content(unassigned_user.username)
end
end
context 'when other notes are destroyed' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
# This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
it 'keeps autocomplete key listeners' do
visit project_issue_path(project, issue)
note = find('#note-body')
start_comment_with_emoji(note)
start_and_cancel_discussion
note.fill_in(with: '')
start_comment_with_emoji(note)
note.native.send_keys(:enter)
expect(note.value).to eql('Hello :100: ')
end
def start_comment_with_emoji(note)
note.native.send_keys('Hello :10')
# Wait for emoji popup
find('.atwho-view li', text: '100')
end
def start_and_cancel_discussion
click_button('Reply...')
fill_in('note_note', with: 'Whoops!')
page.accept_alert 'Are you sure you want to cancel creating this comment?' do
click_button('Cancel')
end
wait_for_requests
end
end
end
private

View File

@ -666,6 +666,97 @@ describe('Api', () => {
});
});
describe('release', () => {
const dummyProjectPath = 'gitlab-org/gitlab';
const dummyTagName = 'v1.3';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
dummyProjectPath,
)}/releases/${encodeURIComponent(dummyTagName)}`;
describe('when the release is successfully returned', () => {
it('resolves the Promise', () => {
mock.onGet(expectedUrl).replyOnce(200);
return Api.release(dummyProjectPath, dummyTagName).then(() => {
expect(mock.history.get).toHaveLength(1);
});
});
});
describe('when an error occurs while fetching the release', () => {
it('rejects the Promise', () => {
mock.onGet(expectedUrl).replyOnce(500);
return Api.release(dummyProjectPath, dummyTagName).catch(() => {
expect(mock.history.get).toHaveLength(1);
});
});
});
});
describe('createRelease', () => {
const dummyProjectPath = 'gitlab-org/gitlab';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
dummyProjectPath,
)}/releases`;
const release = {
name: 'Version 1.0',
};
describe('when the release is successfully created', () => {
it('resolves the Promise', () => {
mock.onPost(expectedUrl, release).replyOnce(201);
return Api.createRelease(dummyProjectPath, release).then(() => {
expect(mock.history.post).toHaveLength(1);
});
});
});
describe('when an error occurs while creating the release', () => {
it('rejects the Promise', () => {
mock.onPost(expectedUrl, release).replyOnce(500);
return Api.createRelease(dummyProjectPath, release).catch(() => {
expect(mock.history.post).toHaveLength(1);
});
});
});
});
describe('updateRelease', () => {
const dummyProjectPath = 'gitlab-org/gitlab';
const dummyTagName = 'v1.3';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
dummyProjectPath,
)}/releases/${encodeURIComponent(dummyTagName)}`;
const release = {
name: 'Version 1.0',
};
describe('when the release is successfully created', () => {
it('resolves the Promise', () => {
mock.onPut(expectedUrl, release).replyOnce(200);
return Api.updateRelease(dummyProjectPath, dummyTagName, release).then(() => {
expect(mock.history.put).toHaveLength(1);
});
});
});
describe('when an error occurs while creating the release', () => {
it('rejects the Promise', () => {
mock.onPut(expectedUrl, release).replyOnce(500);
return Api.updateRelease(dummyProjectPath, dummyTagName, release).catch(() => {
expect(mock.history.put).toHaveLength(1);
});
});
});
});
describe('createReleaseLink', () => {
const dummyProjectPath = 'gitlab-org/gitlab';
const dummyReleaseTag = 'v1.3';

View File

@ -3,13 +3,13 @@
exports[`Design note pin component should match the snapshot of note when repositioning 1`] = `
<button
aria-label="Comment form position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center btn-transparent comment-indicator"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
style="left: 10px; top: 10px; cursor: move;"
type="button"
>
<icon-stub
<gl-icon-stub
name="image-comment-dark"
size="16"
size="24"
/>
</button>
`;
@ -17,7 +17,7 @@ exports[`Design note pin component should match the snapshot of note when reposi
exports[`Design note pin component should match the snapshot of note with index 1`] = `
<button
aria-label="Comment '1' position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center js-image-badge badge badge-pill"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 js-image-badge badge badge-pill"
style="left: 10px; top: 10px;"
type="button"
>
@ -30,13 +30,13 @@ exports[`Design note pin component should match the snapshot of note with index
exports[`Design note pin component should match the snapshot of note without index 1`] = `
<button
aria-label="Comment form position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center btn-transparent comment-indicator"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
style="left: 10px; top: 10px;"
type="button"
>
<icon-stub
<gl-icon-stub
name="image-comment-dark"
size="16"
size="24"
/>
</button>
`;

View File

@ -3,13 +3,13 @@
exports[`Design note pin component should match the snapshot of note when repositioning 1`] = `
<button
aria-label="Comment form position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center btn-transparent comment-indicator"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
style="left: 10px; top: 10px; cursor: move;"
type="button"
>
<icon-stub
<gl-icon-stub
name="image-comment-dark"
size="16"
size="24"
/>
</button>
`;
@ -17,7 +17,7 @@ exports[`Design note pin component should match the snapshot of note when reposi
exports[`Design note pin component should match the snapshot of note with index 1`] = `
<button
aria-label="Comment '1' position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center js-image-badge badge badge-pill"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 js-image-badge badge badge-pill"
style="left: 10px; top: 10px;"
type="button"
>
@ -30,13 +30,13 @@ exports[`Design note pin component should match the snapshot of note with index
exports[`Design note pin component should match the snapshot of note without index 1`] = `
<button
aria-label="Comment form position"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center btn-transparent comment-indicator"
class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
style="left: 10px; top: 10px;"
type="button"
>
<icon-stub
<gl-icon-stub
name="image-comment-dark"
size="16"
size="24"
/>
</button>
`;

View File

@ -182,18 +182,65 @@ RSpec.describe GitlabRoutingHelper do
end
describe '#gitlab_raw_snippet_blob_path' do
let(:snippet) { personal_snippet }
let(:blob) { snippet.blobs.first }
let(:ref) { 'test-ref' }
let(:args) { {} }
it_behaves_like 'snippet blob raw path' do
subject { gitlab_raw_snippet_blob_path(blob, ref) }
subject { gitlab_raw_snippet_blob_path(snippet, blob.path, ref, args) }
it_behaves_like 'snippet blob raw path'
context 'when an argument is set' do
let(:args) { { inline: true } }
it { expect(subject).to eq("/-/snippets/#{personal_snippet.id}/raw/#{ref}/#{blob.path}?inline=true") }
end
context 'without a ref' do
let(:blob) { personal_snippet.blobs.first }
let(:ref) { blob.repository.root_ref }
let(:ref) { nil }
let(:expected_ref) { blob.repository.root_ref }
it 'uses the root ref' do
expect(gitlab_raw_snippet_blob_path(blob)).to eq("/-/snippets/#{personal_snippet.id}/raw/#{ref}/#{blob.path}")
expect(subject).to eq("/-/snippets/#{personal_snippet.id}/raw/#{expected_ref}/#{blob.path}")
end
end
end
describe '#gitlab_raw_snippet_blob_url' do
let(:blob) { snippet.blobs.first }
let(:ref) { 'snippet-test-ref' }
let(:args) { {} }
subject { gitlab_raw_snippet_blob_url(snippet, blob.path, ref, args) }
context 'for a PersonalSnippet' do
let(:snippet) { personal_snippet }
it { expect(subject).to eq("http://test.host/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}") }
end
context 'for a ProjectSnippet' do
let(:snippet) { project_snippet }
it { expect(subject).to eq("http://test.host/#{snippet.project.full_path}/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}") }
end
context 'when an argument is set' do
let(:args) { { inline: true } }
let(:snippet) { personal_snippet }
it { expect(subject).to eq("http://test.host/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}?inline=true") }
end
context 'without a ref' do
let(:snippet) { personal_snippet }
let(:ref) { nil }
let(:expected_ref) { snippet.repository.root_ref }
it 'uses the root ref' do
expect(subject).to eq("http://test.host/-/snippets/#{snippet.id}/raw/#{expected_ref}/#{blob.path}")
end
end
end
@ -208,32 +255,6 @@ RSpec.describe GitlabRoutingHelper do
end
end
describe '#gitlab_raw_snippet_blob_url' do
let(:blob) { snippet.blobs.first }
let(:ref) { 'snippet-test-ref' }
context 'for a PersonalSnippet' do
let(:snippet) { personal_snippet }
it { expect(gitlab_raw_snippet_blob_url(snippet, blob.path, ref)).to eq("http://test.host/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}") }
end
context 'for a ProjectSnippet' do
let(:snippet) { project_snippet }
it { expect(gitlab_raw_snippet_blob_url(snippet, blob.path, ref)).to eq("http://test.host/#{snippet.project.full_path}/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}") }
end
context 'without a ref' do
let(:snippet) { personal_snippet }
let(:ref) { snippet.repository.root_ref }
it 'uses the root ref' do
expect(gitlab_raw_snippet_blob_url(snippet, blob.path)).to eq("http://test.host/-/snippets/#{snippet.id}/raw/#{ref}/#{blob.path}")
end
end
end
describe '#gitlab_snippet_notes_path' do
it 'returns the notes path for the personal snippet' do
expect(gitlab_snippet_notes_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/notes")