Commit ef326e80 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 7515ec41
......@@ -13,6 +13,7 @@ export default class AvailableDropdownMappings {
runnerTagsEndpoint,
labelsEndpoint,
milestonesEndpoint,
releasesEndpoint,
groupsOnly,
includeAncestorGroups,
includeDescendantGroups,
......@@ -21,6 +22,7 @@ export default class AvailableDropdownMappings {
this.runnerTagsEndpoint = runnerTagsEndpoint;
this.labelsEndpoint = labelsEndpoint;
this.milestonesEndpoint = milestonesEndpoint;
this.releasesEndpoint = releasesEndpoint;
this.groupsOnly = groupsOnly;
this.includeAncestorGroups = includeAncestorGroups;
this.includeDescendantGroups = includeDescendantGroups;
......@@ -70,6 +72,19 @@ export default class AvailableDropdownMappings {
},
element: this.container.querySelector('#js-dropdown-milestone'),
},
release: {
reference: null,
gl: DropdownNonUser,
extraArguments: {
endpoint: this.getReleasesEndpoint(),
symbol: '',
// The DropdownNonUser class is hardcoded to look for and display a
// "title" property, so we need to add this property to each release object
preprocessing: releases => releases.map(r => ({ ...r, title: r.tag })),
},
element: this.container.querySelector('#js-dropdown-release'),
},
label: {
reference: null,
gl: DropdownNonUser,
......@@ -130,6 +145,10 @@ export default class AvailableDropdownMappings {
return `${this.milestonesEndpoint}.json`;
}
getReleasesEndpoint() {
return `${this.releasesEndpoint}.json`;
}
getLabelsEndpoint() {
let endpoint = `${this.labelsEndpoint}.json?`;
......
......@@ -11,6 +11,7 @@ export default class FilteredSearchDropdownManager {
runnerTagsEndpoint = '',
labelsEndpoint = '',
milestonesEndpoint = '',
releasesEndpoint = '',
tokenizer,
page,
isGroup,
......@@ -18,10 +19,13 @@ export default class FilteredSearchDropdownManager {
isGroupDecendent,
filteredSearchTokenKeys,
}) {
const removeTrailingSlash = url => url.replace(/\/$/, '');
this.container = FilteredSearchContainer.container;
this.runnerTagsEndpoint = runnerTagsEndpoint.replace(/\/$/, '');
this.labelsEndpoint = labelsEndpoint.replace(/\/$/, '');
this.milestonesEndpoint = milestonesEndpoint.replace(/\/$/, '');
this.runnerTagsEndpoint = removeTrailingSlash(runnerTagsEndpoint);
this.labelsEndpoint = removeTrailingSlash(labelsEndpoint);
this.milestonesEndpoint = removeTrailingSlash(milestonesEndpoint);
this.releasesEndpoint = removeTrailingSlash(releasesEndpoint);
this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
......@@ -54,6 +58,7 @@ export default class FilteredSearchDropdownManager {
this.runnerTagsEndpoint,
this.labelsEndpoint,
this.milestonesEndpoint,
this.releasesEndpoint,
this.groupsOnly,
this.includeAncestorGroups,
this.includeDescendantGroups,
......
......@@ -89,6 +89,7 @@ export default class FilteredSearchManager {
this.filteredSearchInput.getAttribute('data-runner-tags-endpoint') || '',
labelsEndpoint: this.filteredSearchInput.getAttribute('data-labels-endpoint') || '',
milestonesEndpoint: this.filteredSearchInput.getAttribute('data-milestones-endpoint') || '',
releasesEndpoint: this.filteredSearchInput.getAttribute('data-releases-endpoint') || '',
tokenizer: this.tokenizer,
page: this.page,
isGroup: this.isGroup,
......
import FilteredSearchTokenKeys from './filtered_search_token_keys';
import { __ } from '~/locale';
export const tokenKeys = [
export const tokenKeys = [];
tokenKeys.push(
{
key: 'author',
type: 'string',
......@@ -26,15 +28,27 @@ export const tokenKeys = [
icon: 'clock',
tag: '%milestone',
},
{
key: 'label',
type: 'array',
param: 'name[]',
symbol: '~',
icon: 'labels',
tag: '~label',
},
];
);
if (gon && gon.features && gon.features.releaseSearchFilter) {
tokenKeys.push({
key: 'release',
type: 'string',
param: 'tag',
symbol: '',
icon: 'rocket',
tag: __('tag name'),
});
}
tokenKeys.push({
key: 'label',
type: 'array',
param: 'name[]',
symbol: '~',
icon: 'labels',
tag: '~label',
});
if (gon.current_user_id) {
// Appending tokenkeys only logged-in
......@@ -88,6 +102,16 @@ export const conditions = [
tokenKey: 'milestone',
value: __('Started'),
},
{
url: 'release_tag=None',
tokenKey: 'release',
value: __('None'),
},
{
url: 'release_tag=Any',
tokenKey: 'release',
value: __('Any'),
},
{
url: 'label_name[]=None',
tokenKey: 'label',
......
......@@ -76,7 +76,7 @@ export default {
},
shouldShowEditButton() {
return Boolean(
this.glFeatures.releaseEditPage && this.release._links && this.release._links.edit,
this.glFeatures.releaseEditPage && this.release._links && this.release._links.edit_url,
);
},
},
......@@ -108,7 +108,7 @@ export default {
v-gl-tooltip
class="btn btn-default js-edit-button ml-2"
:title="__('Edit this release')"
:href="release._links.edit"
:href="release._links.edit_url"
>
<icon name="pencil" />
</gl-link>
......
......@@ -44,6 +44,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, project.group)
push_frontend_feature_flag(:release_search_filter, project)
end
respond_to :html
......
......@@ -2,12 +2,24 @@
class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :require_non_empty_project, except: [:index]
before_action :authorize_read_release!
before_action do
push_frontend_feature_flag(:release_edit_page, project)
end
def index
respond_to do |format|
format.html do
require_non_empty_project
end
format.json { render json: releases }
end
end
protected
def releases
ReleasesFinder.new(@project, current_user).execute
end
end
......@@ -236,6 +236,7 @@ module SearchHelper
opts[:data]['project-id'] = @project.id
opts[:data]['labels-endpoint'] = project_labels_path(@project)
opts[:data]['milestones-endpoint'] = project_milestones_path(@project)
opts[:data]['releases-endpoint'] = project_releases_path(@project)
elsif @group.present?
opts[:data]['group-id'] = @group.id
opts[:data]['labels-endpoint'] = group_labels_path(@group)
......
......@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
VERSION = '0.10.0'
VERSION = '0.10.1'
self.table_name = 'clusters_applications_runners'
......
......@@ -91,6 +91,19 @@
%li.filter-dropdown-item
%button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
#js-dropdown-release.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
%button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
......
---
title: Enable image link and lazy loading in AsciiDoc documents
merge_request: 18164
author: Guillaume Grossetie
type: fixed
---
title: Add "release" filter to issue search page
merge_request: 18761
author:
type: added
---
title: Allow release block edit button to be visible
merge_request: 19226
author:
type: fixed
---
title: Update GitLab Runner Helm Chart to 0.10.1
merge_request: 19232
author:
type: other
This diff is collapsed.
......@@ -166,12 +166,11 @@ end
Normally, GitLab CE/EE tests use a local clone of Gitaly in
`tmp/tests/gitaly` pinned at the version specified in
`GITALY_SERVER_VERSION`. The `GITALY_SERVER_VERSION` file supports
`=my-branch` syntax to use a custom branch in <https://gitlab.com/gitlab-org/gitaly>. If
`GITALY_SERVER_VERSION`. The `GITALY_SERVER_VERSION` file supports also
branches and SHA to use a custom commit in <https://gitlab.com/gitlab-org/gitaly>. If
you want to run tests locally against a modified version of Gitaly you
can replace `tmp/tests/gitaly` with a symlink. This is much faster
because the `=my-branch` syntax forces a Gitaly re-install each time
you run `rspec`.
because if will avoid a Gitaly re-install each time you run `rspec`.
```shell
rm -rf tmp/tests/gitaly
......
......@@ -5,7 +5,7 @@
In April 2019, Francisco Javier López hosted a [Deep Dive] on GitLab's [Git LFS] implementation to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube], and the slides on [Google Slides] and in [PDF]. Everything covered in this deep dive was accurate as of GitLab 11.10, and while specific details may have changed since then, it should still serve as a good introduction.
[Deep Dive]: https://gitlab.com/gitlab-org/create-stage/issues/1
[Git LFS]: ../workflow/lfs/manage_large_binaries_with_git_lfs.html
[Git LFS]: ../administration/lfs/manage_large_binaries_with_git_lfs.md
[recording on YouTube]: https://www.youtube.com/watch?v=Yyxwcksr0Qc
[Google Slides]: https://docs.google.com/presentation/d/1E-aw6-z0rYd0346YhIWE7E9A65zISL9iIMAOq2zaw9E/edit
[PDF]: https://gitlab.com/gitlab-org/create-stage/uploads/07a89257a140db067bdfb484aecd35e1/Git_LFS_Deep_Dive__Create_.pdf
......@@ -136,7 +136,7 @@ If you want to import projects from Bitbucket, but don't want to enable signing
you can [disable Sign-Ins in the admin panel](omniauth.md#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources).
[init-oauth]: omniauth.md#initial-omniauth-configuration
[bb-import]: ../workflow/importing/import_projects_from_bitbucket.md
[bb-import]: ../user/project/import/bitbucket.md
[bb-old]: https://gitlab.com/gitlab-org/gitlab/blob/8-14-stable/doc/integration/bitbucket.md
[bitbucket-docs]: https://confluence.atlassian.com/bitbucket/use-the-ssh-protocol-with-bitbucket-cloud-221449711.html#UsetheSSHprotocolwithBitbucketCloud-KnownhostorBitbucket%27spublickeyfingerprints
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
......
......@@ -18,7 +18,7 @@ Create issues, labels, milestones, cast your vote, and review issues.
- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue)
- [Assign labels to issues](../user/project/labels.md)
- [Use milestones as an overview of your project's tracker](../user/project/milestones/index.md)
- [Use voting to express your like/dislike to issues and merge requests](../workflow/award_emoji.md)
- [Use voting to express your like/dislike to issues and merge requests](../user/award_emojis.md)
## Collaborate
......
......@@ -85,7 +85,7 @@ The following relate to Git Large File Storage:
- [Getting Started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/)
- [Migrate an existing Git repo with Git LFS](migrate_to_git_lfs/index.md)
- [GitLab Git LFS user documentation](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
- [GitLab Git LFS admin documentation](../../workflow/lfs/lfs_administration.md)
- [git-annex to Git-LFS migration guide](../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md)
- [GitLab Git LFS user documentation](../../administration/lfs/manage_large_binaries_with_git_lfs.md)
- [GitLab Git LFS admin documentation](../../administration/lfs/lfs_administration.md)
- [git-annex to Git-LFS migration guide](../../administration/lfs/migrate_from_git_annex_to_git_lfs.md)
- [Towards a production quality open source Git LFS server](https://about.gitlab.com/blog/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
......@@ -170,7 +170,7 @@ Some tickets need specific knowledge or a deep understanding of a particular com
Move on to understanding some of GitLab's more advanced features. You can make use of GitLab.com to understand the features from an end-user perspective and then use your own instance to understand setup and configuration of the feature from an Administrative perspective
- Set up and try [Git LFS](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
- Set up and try [Git LFS](../../administration/lfs/manage_large_binaries_with_git_lfs.md)
- Get to know the [GitLab API](../../api/README.md), its capabilities and shortcomings
- Learn how to [migrate from SVN to Git](../../user/project/import/svn.md)
- Set up [GitLab CI](../../ci/quick_start/README.md)
......
# Dependency Proxy **(PREMIUM)**
# Dependency Proxy **(PREMIUM ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
......
......@@ -22,12 +22,12 @@ For an overview, see the video [Design Management (GitLab 12.2)](https://www.you
## Requirements
Design Management requires
[Large File Storage (LFS)](../../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
[Large File Storage (LFS)](../../../administration/lfs/manage_large_binaries_with_git_lfs.md)
to be enabled:
- For GitLab.com, LFS is already enabled.
- For self-managed instances, a GitLab administrator must have
[enabled LFS globally](../../../workflow/lfs/lfs_administration.md).
[enabled LFS globally](../../../administration/lfs/lfs_administration.md).
- For both GitLab.com and self-managed instances: LFS must be enabled for the project itself.
If enabled globally, LFS will be enabled by default to all projects. To enable LFS on the
project level, navigate to your project's **Settings > General**, expand **Visibility, project features, permissions**
......
......@@ -15,7 +15,7 @@ project.
![Find file button](img/file_finder_find_button.png)
For those who prefer to keep their fingers on the keyboard, there is a
[shortcut button](../../../workflow/shortcuts.md) as well, which you can invoke from _anywhere_
[shortcut button](../../shortcuts.md) as well, which you can invoke from _anywhere_
in a project.
Press `t` to launch the File search function when in **Issues**,
......
......@@ -7,7 +7,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/forking_workflow.html'
Forking a project to your own namespace is useful if you have no write
access to the project you want to contribute to. If you do have write
access or can request it, we recommend working together in the same
repository since it is simpler. See our [GitLab Flow](../../../workflow/gitlab_flow.md)
repository since it is simpler. See our [GitLab Flow](../../../topics/gitlab_flow.md)
document more information about using branches to work together.
## Creating a fork
......
......@@ -43,7 +43,7 @@ A To Do displays on your To-Do List when:
- The author
- Have set it to automatically merge once the pipeline succeeds
To-do triggers are not affected by [GitLab Notification Email settings](../workflow/notifications.md).
To-do triggers are not affected by [GitLab Notification Email settings](profile/notifications.md).
NOTE: **Note:**
When a user no longer has access to a resource related to a To Do (like an issue, merge request, project, or group) the related To-Do items are deleted within the next hour for security reasons. The delete is delayed to prevent data loss, in case the user's access was revoked by mistake.
......
......@@ -2,43 +2,10 @@
comments: false
---
# Workflow
# Workflow (Deprecated)
- [Automatic issue closing](../user/project/issues/managing_issues.md#closing-issues-automatically)
- [Cycle Analytics](../user/project/cycle_analytics.md)
- [Description templates](../user/project/description_templates.md)
- [Feature branch workflow](../gitlab-basics/feature_branch_workflow.md)
- [Groups](../user/group/index.md)
- Issues - The GitLab Issue Tracker is an advanced and complete tool for
tracking the evolution of a new idea or the process of solving a problem.
- [Exporting Issues](../user/project/issues/csv_export.md) **(STARTER)** Export issues as a CSV, emailed as an attachment.
- [Confidential issues](../user/project/issues/confidential_issues.md)
- [Due date for issues](../user/project/issues/due_dates.md)
- [Issue Board](../user/project/issue_board.md)
- [File finder](../user/project/repository/file_finder.md)
- [File lock](../user/project/file_lock.md) **(PREMIUM)**
- [Labels](../user/project/labels.md)
- [Projects](../user/project/index.md)
- [Project forking workflow](../user/project/repository/forking_workflow.md)
- [Project users](../user/project/members/index.md)
- [Protected branches](../user/project/protected_branches.md)
- [Protected tags](../user/project/protected_tags.md)
- [Quick Actions](../user/project/quick_actions.md)
- [Sharing projects with groups](../user/project/members/share_project_with_groups.md)
- [Web Editor](../user/project/repository/web_editor.md)
- [Milestones](../user/project/milestones/index.md)
- [Merge Requests](../user/project/merge_requests/index.md)
- [Authorization for merge requests](../user/project/merge_requests/authorization_for_merge_requests.md)
- [Cherry-pick changes](../user/project/merge_requests/cherry_pick_changes.md)
- [Merge when pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md)
- [Resolve threads in merge requests reviews](../user/discussions/index.md)
- [Resolve merge conflicts in the UI](../user/project/merge_requests/resolve_conflicts.md)
- [Revert changes in the UI](../user/project/merge_requests/revert_changes.md)
- [Merge requests versions](../user/project/merge_requests/versions.md)
- ["Work In Progress" merge requests](../user/project/merge_requests/work_in_progress_merge_requests.md)
- [Fast-forward merge requests](../user/project/merge_requests/fast_forward_merge.md)
- [Merge request approvals](../user/project/merge_requests/merge_request_approvals.md) **(STARTER)**
- [Service Desk](../user/project/service_desk.md) **(PREMIUM)**
- [Importing from SVN, GitHub, Bitbucket, etc](../user/project/import/index.md)
- [Snippets](../user/snippets.md)
- [Subgroups](../user/group/subgroups/index.md)
This page was deprecated, with all content previously stored under the `/workflow` path moved
to other locations in the documentation site, organized by topic. You can use the search
box to find the content you are looking for, browse the main [GitLab Documentation page](../README.md),
or view the [issue that deprecated this page](https://gitlab.com/gitlab-org/gitlab/issues/32940)
for more details.
......@@ -11,6 +11,8 @@ module Banzai
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
Filter::ColorFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
Filter::AsciiDocPostProcessingFilter
]
end
......
......@@ -158,15 +158,17 @@ module Gitlab
end
def checkout_or_clone_version(version:, repo:, target_dir:)
version =
if version.starts_with?("=")
version.sub(/\A=/, '') # tag or branch
else
"v#{version}" # tag
end
clone_repo(repo, target_dir) unless Dir.exist?(target_dir)
checkout_version(version, target_dir)
checkout_version(get_version(version), target_dir)
end
# this function implements the same logic we have in omnibus for dealing with components version
def get_version(component_version)
# If not a valid version string following SemVer it is probably a branch name or a SHA
# commit of one of our own component so it doesn't need `v` prepended
return component_version unless /^\d+\.\d+\.\d+(-rc\d+)?$/.match?(component_version)
"v#{component_version}"
end
def clone_repo(repo, target_dir)
......
......@@ -20497,6 +20497,9 @@ msgstr ""
msgid "syntax is incorrect"
msgstr ""
msgid "tag name"
msgstr ""
msgid "this document"
msgstr ""
......
......@@ -14,10 +14,10 @@ gitlab:
gitaly:
resources:
requests:
cpu: 300m
cpu: 600m
memory: 200M
limits:
cpu: 600m
cpu: 1200m
memory: 420M
persistence:
size: 10G
......@@ -46,10 +46,10 @@ gitlab:
sidekiq:
resources:
requests:
cpu: 300m
cpu: 500m
memory: 800M
limits:
cpu: 400m
cpu: 1000m
memory: 1.6G
task-runner:
resources:
......
......@@ -3,10 +3,13 @@
require 'spec_helper'
describe Projects::ReleasesController do
let!(:project) { create(:project, :repository, :public) }
let!(:user) { create(:user) }
let!(:project) { create(:project, :repository, :public) }
let!(:private_project) { create(:project, :repository, :private) }
let!(:user) { create(:user) }
let!(:release_1) { create(:release, project: project, released_at: Time.zone.parse('2018-10-18')) }
let!(:release_2) { create(:release, project: project, released_at: Time.zone.parse('2019-10-19')) }
describe 'GET #index' do
shared_examples 'common access controls' do
it 'renders a 200' do
get_index
......@@ -14,17 +17,14 @@ describe Projects::ReleasesController do
end
context 'when the project is private' do
let!(:project) { create(:project, :repository, :private) }
it 'renders a 302' do
get_index
let(:project) { private_project }
expect(response.status).to eq(302)
before do
sign_in(user)
end
it 'renders a 200 for a logged in developer' do
project.add_developer(user)
sign_in(user)
get_index
......@@ -32,8 +32,6 @@ describe Projects::ReleasesController do
end
it 'renders a 404 when logged in but not in the project' do
sign_in(user)
get_index
expect(response.status).to eq(404)
......@@ -41,9 +39,55 @@ describe Projects::ReleasesController do
end
end
describe 'GET #index' do
before do
get_index
end
context 'as html' do
let(:format) { :html }
it 'returns a text/html content_type' do
expect(response.content_type).to eq 'text/html'
end
it_behaves_like 'common access controls'
context 'when the project is private and the user is not logged in' do
let(:project) { private_project }
it 'renders a 302' do
expect(response.status).to eq(302)
end
end
end
context 'as json' do
let(:format) { :json }
it 'returns an application/json content_type' do
expect(response.content_type).to eq 'application/json'
end
it "returns the project's releases as JSON, ordered by released_at" do
expect(response.body).to eq([release_2, release_1].to_json)
end
it_behaves_like 'common access controls'
context 'when the project is private and the user is not logged in' do
let(:project) { private_project }
it 'renders a 401' do
expect(response.status).to eq(401)
end
end
end
end
private
def get_index
get :index, params: { namespace_id: project.namespace, project_id: project }
get :index, params: { namespace_id: project.namespace, project_id: project, format: format }
end
end
......@@ -68,7 +68,7 @@ describe 'Dropdown hint', :js do
it 'filters with text' do
filtered_search.set('a')
expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
end
end
......@@ -104,6 +104,15 @@ describe 'Dropdown hint', :js do
expect_filtered_search_input_empty
end
it 'opens the release dropdown when you click on release' do
click_hint('release')
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-release', visible: true)
expect_tokens([{ name: 'Release' }])
expect_filtered_search_input_empty
end
it 'opens the label dropdown when you click on label' do
click_hint('label')
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Dropdown release', :js do
include FilteredSearchHelpers
let!(:project) { create(:project, :repository) }
let!(:user) { create(:user) }
let!(:release) { create(:release, tag: 'v1.0', project: project) }
let!(:crazy_release) { create(:release, tag: '☺!/"#%&\'{}+,-.<>;=@]_`{|}🚀', project: project) }
def filtered_search
find('.filtered-search')
end
def filter_dropdown
find('#js-dropdown-release .filter-dropdown')
end
before do
project.add_maintainer(user)
sign_in(user)
create(:issue, project: project)
visit project_issues_path(project)
end
describe 'behavior' do
before do
filtered_search.set('release:')
end
def expect_results(count)
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: count)
end
it 'loads all the releases when opened' do
expect_results(2)
end
it 'filters by tag name' do
filtered_search.send_keys("☺")
expect_results(1)
end
it 'fills in the release name when the autocomplete hint is clicked' do
find('#js-dropdown-release .filter-dropdown-item', text: crazy_release.tag).click
expect(page).to have_css('#js-dropdown-release', visible: false)
expect_tokens([release_token(crazy_release.tag)])
expect_filtered_search_input_empty
end
end
end
......@@ -73,7 +73,7 @@ describe('Release block', () => {
it('renders an edit button that links to the "Edit release" page', () => {
expect(editButton().exists()).toBe(true);
expect(editButton().attributes('href')).toBe(release._links.edit);
expect(editButton().attributes('href')).toBe(release._links.edit_url);
});
it('renders release name', () => {
......@@ -180,7 +180,7 @@ describe('Release block', () => {
});
});
it("does not render an edit button if release._links.edit isn't a string", () => {
it("does not render an edit button if release._links.edit_url isn't a string", () => {
delete releaseClone._links;
return factory(releaseClone).then(() => {
......
......@@ -95,6 +95,6 @@ export const release = {
],
},
_links: {
edit: 'http://0.0.0.0:3001/root/release-test/-/releases/v0.3/edit',
edit_url: 'http://0.0.0.0:3001/root/release-test/-/releases/v0.3/edit',
},
};
......@@ -167,6 +167,7 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['runner-tags-endpoint']).to eq(tag_list_admin_runners_path)
expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(project_labels_path(@project))
expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(project_milestones_path(@project))
expect(search_filter_input_options('')[:data]['releases-endpoint']).to eq(project_releases_path(@project))
end
it 'includes autocomplete=off flag' do
......
......@@ -58,7 +58,7 @@ module Gitlab
},
'image with onerror' => {
input: 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]',
output: "<div>\n<p><span><img src=\"https://localhost.com/image.png\" alt='Alt text\" onerror=\"alert(7)'></span></p>\n</div>"
output: "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt='Alt text\" onerror=\"alert(7)' class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
},
'fenced code with inline script' => {
input: '```mypre"><script>alert(3)</script>',
......@@ -73,6 +73,20 @@ module Gitlab
end
end
context "images" do
it "does lazy load and link image" do
input = 'image:https://localhost.com/image.png[]'
output = "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
expect(render(input, context)).to include(output)
end
it "does not automatically link image if link is explicitly defined" do
input = 'image:https://localhost.com/image.png[link=https://gitlab.com]'
output = "<div>\n<p><span><a href=\"https://gitlab.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
expect(render(input, context)).to include(output)
end
end
context 'with admonition' do
it 'preserves classes' do
input = <<~ADOC
......@@ -107,7 +121,7 @@ module Gitlab
ADOC
output = <<~HTML
<h2>Title</h2>
<h2>Title</h2>
HTML
expect(render(input, context)).to include(output.strip)
......@@ -149,15 +163,15 @@ module Gitlab
ADOC
output = <<~HTML
<div>
<p>This paragraph has a footnote.<sup>[<a id="_footnoteref_1" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
</div>
<div>
<hr>
<div id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. This is the text of the footnote.
</div>
</div>
<div>
<p>This paragraph has a footnote.<sup>[<a id="_footnoteref_1" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
</div>
<div>
<hr>
<div id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. This is the text of the footnote.
</div>
</div>
HTML
expect(render(input, context)).to include(output.strip)
......@@ -183,34 +197,34 @@ module Gitlab
ADOC
output = <<~HTML
<h1>Title</h1>
<div>
<h2 id="user-content-first-section">
<a class="anchor" href="#user-content-first-section"></a>First section</h2>
<div>
<div>
<p>This is the first section.</p>
</div>
</div>
</div>
<div>
<h2 id="user-content-second-section">
<a class="anchor" href="#user-content-second-section"></a>Second section</h2>
<div>
<div>
<p>This is the second section.</p>
</div>
</div>
</div>
<div>
<h2 id="user-content-thunder">
<a class="anchor" href="#user-content-thunder"></a>Thunder ⚡ !</h2>
<div>
<div>
<p>This is the third section.</p>
</div>
</div>
</div>
<h1>Title</h1>
<div>
<h2 id="user-content-first-section">
<a class="anchor" href="#user-content-first-section"></a>First section</h2>
<div>
<div>
<p>This is the first section.</p>
</div>
</div>
</div>
<div>
<h2 id="user-content-second-section">
<a class="anchor" href="#user-content-second-section"></a>Second section</h2>
<div>
<div>
<p>This is the second section.</p>
</div>
</div>
</div>
<div>
<h2 id="user-content-thunder">
<a class="anchor" href="#user-content-thunder"></a>Thunder ⚡ !</h2>
<div>
<div>
<p>This is the third section.</p>
</div>
</div>
</div>
HTML
expect(render(input, context)).to include(output.strip)
......
......@@ -114,6 +114,10 @@ module FilteredSearchHelpers
create_token('Milestone', milestone_name, symbol)
end
def release_token(release_tag = nil)
create_token('Release', release_tag)
end
def label_token(label_name = nil, has_symbol = true)
symbol = has_symbol ? '~' : nil
create_token('Label', label_name, symbol)
......
......@@ -20,22 +20,12 @@ describe Gitlab::TaskHelpers do
end
it 'checkout the version and reset to it' do
expect(subject).to receive(:get_version).with(version).and_call_original
expect(subject).to receive(:checkout_version).with(tag, clone_path)
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
end
context 'with a branch version' do
let(:version) { '=branch_name' }
let(:branch) { 'branch_name' }
it 'checkout the version and reset to it with a branch name' do
expect(subject).to receive(:checkout_version).with(branch, clone_path)
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
end
end
context "target_dir doesn't exist" do
it 'clones the repo' do
expect(subject).to receive(:clone_repo).with(repo, clone_path)
......@@ -96,4 +86,19 @@ describe Gitlab::TaskHelpers do
expect { subject.run_command!(['bash', '-c', 'exit 1']) }.to raise_error Gitlab::TaskFailedError
end
end
describe '#get_version' do
using RSpec::Parameterized::TableSyntax
where(:version, :result) do
'1.1.1' | 'v1.1.1'
'master' | 'master'
'12.4.0-rc7' | 'v12.4.0-rc7'
'594c3ea3e0e5540e5915bd1c49713a0381459dd6' | '594c3ea3e0e5540e5915bd1c49713a0381459dd6'
end
with_them do
it { expect(subject.get_version(version)).to eq(result) }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment