Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
be25f261
Commit
be25f261
authored
Jul 31, 2015
by
Douwe Maan
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into project-buttons
parents
7ba76520
a51a3fb8
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
468 additions
and
337 deletions
+468
-337
CHANGELOG
CHANGELOG
+3
-1
app/models/group.rb
app/models/group.rb
+6
-0
app/models/project.rb
app/models/project.rb
+3
-4
lib/api/entities.rb
lib/api/entities.rb
+10
-0
lib/backup/database.rb
lib/backup/database.rb
+5
-2
lib/backup/manager.rb
lib/backup/manager.rb
+0
-2
lib/backup/repository.rb
lib/backup/repository.rb
+4
-1
lib/backup/uploads.rb
lib/backup/uploads.rb
+5
-1
lib/gitlab/markdown/relative_link_filter.rb
lib/gitlab/markdown/relative_link_filter.rb
+12
-2
lib/tasks/gitlab/check.rake
lib/tasks/gitlab/check.rake
+4
-4
spec/features/markdown_spec.rb
spec/features/markdown_spec.rb
+116
-311
spec/fixtures/markdown.md.erb
spec/fixtures/markdown.md.erb
+10
-3
spec/lib/gitlab/markdown/relative_link_filter_spec.rb
spec/lib/gitlab/markdown/relative_link_filter_spec.rb
+16
-0
spec/models/project_spec.rb
spec/models/project_spec.rb
+12
-6
spec/support/markdown_feature.rb
spec/support/markdown_feature.rb
+106
-0
spec/support/matchers/markdown_matchers.rb
spec/support/matchers/markdown_matchers.rb
+156
-0
No files found.
CHANGELOG
View file @
be25f261
...
...
@@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 7.14.0 (unreleased)
- Fix network graph when branch name has single quotes (Stan Hu)
- Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu)
- Add support for Unicode filenames in relative links (Hiroyuki Sato)
- Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki)
- Fix commit data retrieval when branch name has single quotes (Stan Hu)
- Check that project was actually created rather than just validated in import:repos task (Stan Hu)
...
...
@@ -17,9 +18,11 @@ v 7.14.0 (unreleased)
- Expire Rails cache entries after two weeks to prevent endless Redis growth
- Add support for destroying project milestones (Stan Hu)
- Add fetch command to the MR page
- Add project star and fork count, group avatar URL and user/group web URL attributes to API
- Fix bug causing Bitbucket importer to crash when OAuth application had been removed.
- Add fetch command to the MR page.
- Tweak project page buttons.
- Disabled autocapitalize and autocorrect on login field (Daryl Chan)
v 7.13.2
- Fix randomly failed spec
...
...
@@ -30,7 +33,6 @@ v 7.13.2
- Show the first tab automatically on MergeRequests#new
- Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt)
- Fix Gmail Actions
- Disabled autocapitalize and autocorrect on login field (Daryl Chan)
v 7.13.1
- Fix: Label modifications are not reflected in existing notes and in the issue list
...
...
app/models/group.rb
View file @
be25f261
...
...
@@ -56,6 +56,12 @@ class Group < Namespace
name
end
def
avatar_url
(
size
=
nil
)
if
avatar
.
present?
[
gitlab_config
.
url
,
avatar
.
url
].
join
end
end
def
owners
@owners
||=
group_members
.
owners
.
map
(
&
:user
)
end
...
...
app/models/project.rb
View file @
be25f261
...
...
@@ -36,7 +36,6 @@ class Project < ActiveRecord::Base
include
Gitlab
::
ConfigHelper
include
Gitlab
::
ShellAdapter
include
Gitlab
::
VisibilityLevel
include
Rails
.
application
.
routes
.
url_helpers
include
Referable
include
Sortable
...
...
@@ -316,7 +315,7 @@ class Project < ActiveRecord::Base
end
def
web_url
[
gitlab_config
.
url
,
path_with_namespace
].
join
(
'/'
)
Rails
.
application
.
routes
.
url_helpers
.
namespace_project_url
(
self
.
namespace
,
self
)
end
def
web_url_without_protocol
...
...
@@ -433,7 +432,7 @@ class Project < ActiveRecord::Base
if
avatar
.
present?
[
gitlab_config
.
url
,
avatar
.
url
].
join
elsif
avatar_in_git
[
gitlab_config
.
url
,
namespace_project_avatar_path
(
namespace
,
self
)].
join
Rails
.
application
.
routes
.
url_helpers
.
namespace_project_avatar_url
(
namespace
,
self
)
end
end
...
...
@@ -571,7 +570,7 @@ class Project < ActiveRecord::Base
end
def
http_url_to_repo
[
gitlab_config
.
url
,
'/'
,
path_with_namespace
,
'.git'
].
join
(
''
)
"
#{
web_url
}
.git"
end
# Check if current branch name is marked as protected in the system
...
...
lib/api/entities.rb
View file @
be25f261
...
...
@@ -6,6 +6,10 @@ module API
class
UserBasic
<
UserSafe
expose
:id
,
:state
,
:avatar_url
expose
:web_url
do
|
user
,
options
|
Rails
.
application
.
routes
.
url_helpers
.
user_url
(
user
)
end
end
class
User
<
UserBasic
...
...
@@ -59,6 +63,7 @@ module API
expose
:namespace
expose
:forked_from_project
,
using:
Entities
::
ForkedFromProject
,
if:
lambda
{
|
project
,
options
|
project
.
forked?
}
expose
:avatar_url
expose
:star_count
,
:forks_count
end
class
ProjectMember
<
UserBasic
...
...
@@ -69,6 +74,11 @@ module API
class
Group
<
Grape
::
Entity
expose
:id
,
:name
,
:path
,
:description
expose
:avatar_url
expose
:web_url
do
|
group
,
options
|
Rails
.
application
.
routes
.
url_helpers
.
group_url
(
group
)
end
end
class
GroupDetail
<
Group
...
...
lib/backup/database.rb
View file @
be25f261
...
...
@@ -7,7 +7,11 @@ module Backup
def
initialize
@config
=
YAML
.
load_file
(
File
.
join
(
Rails
.
root
,
'config'
,
'database.yml'
))[
Rails
.
env
]
@db_dir
=
File
.
join
(
Gitlab
.
config
.
backup
.
path
,
'db'
)
FileUtils
.
mkdir_p
(
@db_dir
)
unless
Dir
.
exists?
(
@db_dir
)
FileUtils
.
rm_rf
(
@db_dir
)
# Ensure the parent dir of @db_dir exists
FileUtils
.
mkdir_p
(
Gitlab
.
config
.
backup
.
path
)
# Fail if somebody raced to create @db_dir before us
FileUtils
.
mkdir
(
@db_dir
,
mode:
0700
)
end
def
dump
...
...
@@ -25,7 +29,6 @@ module Backup
abort
'Backup failed'
unless
success
$progress
.
print
'Compressing database ... '
FileUtils
.
rm_f
db_file_name_gz
success
=
system
(
'gzip'
,
db_file_name
)
report_success
(
success
)
abort
'Backup failed: compress error'
unless
success
...
...
lib/backup/manager.rb
View file @
be25f261
...
...
@@ -16,8 +16,6 @@ module Backup
file
<<
s
.
to_yaml
.
gsub
(
/^---\n/
,
''
)
end
FileUtils
.
chmod
(
0700
,
folders_to_backup
)
# create archive
$progress
.
print
"Creating backup archive:
#{
tar_file
}
... "
orig_umask
=
File
.
umask
(
0077
)
...
...
lib/backup/repository.rb
View file @
be25f261
...
...
@@ -130,7 +130,10 @@ module Backup
def
prepare
FileUtils
.
rm_rf
(
backup_repos_path
)
FileUtils
.
mkdir_p
(
backup_repos_path
)
# Ensure the parent dir of backup_repos_path exists
FileUtils
.
mkdir_p
(
Gitlab
.
config
.
backup
.
path
)
# Fail if somebody raced to create backup_repos_path before us
FileUtils
.
mkdir
(
backup_repos_path
,
mode:
0700
)
end
def
silent
...
...
lib/backup/uploads.rb
View file @
be25f261
...
...
@@ -10,7 +10,11 @@ module Backup
# Copy uploads from public/uploads to backup/uploads
def
dump
FileUtils
.
mkdir_p
(
backup_uploads_dir
)
FileUtils
.
rm_rf
(
backup_uploads_dir
)
# Ensure the parent dir of backup_uploads_dir exists
FileUtils
.
mkdir_p
(
Gitlab
.
config
.
backup
.
path
)
# Fail if somebody raced to create backup_uploads_dir before us
FileUtils
.
mkdir
(
backup_uploads_dir
,
mode:
0700
)
FileUtils
.
cp_r
(
app_uploads_dir
,
backup_dir
)
end
...
...
lib/gitlab/markdown/relative_link_filter.rb
View file @
be25f261
...
...
@@ -98,15 +98,25 @@ module Gitlab
#
# Returns a String
def
path_type
(
path
)
if
repository
.
tree
(
current_sha
,
path
).
entries
.
any?
unescaped_path
=
Addressable
::
URI
.
unescape
(
path
)
if
tree?
(
unescaped_path
)
'tree'
elsif
repository
.
blob_at
(
current_sha
,
path
).
try
(
:image?
)
elsif
image?
(
unescaped_path
)
'raw'
else
'blob'
end
end
def
tree?
(
path
)
repository
.
tree
(
current_sha
,
path
).
entries
.
any?
end
def
image?
(
path
)
repository
.
blob_at
(
current_sha
,
path
).
try
(
:image?
)
end
def
current_sha
context
[
:commit
].
try
(
:id
)
||
ref
?
repository
.
commit
(
ref
).
try
(
:sha
)
:
repository
.
head_commit
.
sha
...
...
lib/tasks/gitlab/check.rake
View file @
be25f261
...
...
@@ -485,7 +485,8 @@ namespace :gitlab do
if
project
.
empty_repo?
puts
"repository is empty"
.
magenta
elsif
File
.
realpath
(
project_hook_directory
)
==
File
.
realpath
(
gitlab_shell_hooks_path
)
elsif
File
.
directory?
(
project_hook_directory
)
&&
File
.
directory?
(
gitlab_shell_hooks_path
)
&&
(
File
.
realpath
(
project_hook_directory
)
==
File
.
realpath
(
gitlab_shell_hooks_path
))
puts
'ok'
.
green
else
puts
"wrong or missing hooks"
.
red
...
...
@@ -806,4 +807,3 @@ namespace :gitlab do
end
end
end
spec/features/markdown_spec.rb
View file @
be25f261
...
...
@@ -17,410 +17,215 @@ require 'erb'
# -> Post-process HTML
# -> `gfm_with_options` helper
# -> HTML::Pipeline
# -> Sanitize
# -> RelativeLink
# -> Emoji
# -> Table of Contents
# -> Autolinks
# -> Rinku (http, https, ftp)
# -> Other schemes
# -> ExternalLink
# -> References
# -> TaskList
# -> SanitizationFilter
# -> Other filters, depending on pipeline
# -> `html_safe`
# -> Template
#
# See the MarkdownFeature class for setup details.
describe
'GitLab Markdown'
,
feature:
true
do
include
ActionView
::
Helpers
::
TagHelper
include
ActionView
::
Helpers
::
UrlHelper
include
Capybara
::
Node
::
Matchers
include
GitlabMarkdownHelper
include
MarkdownMatchers
# `markdown` calls these two methods
def
current_user
@feat
.
user
end
def
user_color_scheme_class
:white
end
# Let's only parse this thing once
before
(
:all
)
do
@feat
=
MarkdownFeature
.
new
# `markdown` expects a `@project` variable
@project
=
@feat
.
project
@md
=
markdown
(
@feat
.
raw_markdown
)
@doc
=
Nokogiri
::
HTML
::
DocumentFragment
.
parse
(
@md
)
# Sometimes it can be useful to see the parsed output of the Markdown document
# for debugging. Call this method to write the output to
# `tmp/capybara/<filename>.html`.
def
write_markdown
(
filename
=
'markdown_spec'
)
File
.
open
(
Rails
.
root
.
join
(
"tmp/capybara/
#{
filename
}
.html"
),
'w'
)
do
|
file
|
file
.
puts
@html
end
after
(
:all
)
do
@feat
.
teardown
end
# Given a header ID, goes to that element's parent (the header itself), then
# its next sibling element (the body).
def
get_section
(
id
)
@doc
.
at_css
(
"#
#{
id
}
"
).
parent
.
next_element
def
doc
(
html
=
@html
)
Nokogiri
::
HTML
::
DocumentFragment
.
parse
(
html
)
end
# Sometimes it can be useful to see the parsed output of the Markdown document
# for debugging. Uncomment this block to write the output to
# tmp/capybara/markdown_spec.html.
#
# it 'writes to a file' do
# File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file|
# file.puts @md
# end
# end
describe
'Markdown'
do
describe
'No Intra Emphasis'
do
# Shared behavior that all pipelines should exhibit
shared_examples
'all pipelines'
do
describe
'Redcarpet extensions'
do
it
'does not parse emphasis inside of words'
do
body
=
get_section
(
'no-intra-emphasis'
)
expect
(
body
.
to_html
).
not_to
match
(
'foo<em>bar</em>baz'
)
end
expect
(
doc
.
to_html
).
not_to
match
(
'foo<em>bar</em>baz'
)
end
describe
'Tables'
do
it
'parses table Markdown'
do
body
=
get_section
(
'tables'
)
expect
(
body
).
to
have_selector
(
'th:contains("Header")'
)
expect
(
body
).
to
have_selector
(
'th:contains("Row")'
)
expect
(
body
).
to
have_selector
(
'th:contains("Example")'
)
aggregate_failures
do
expect
(
doc
).
to
have_selector
(
'th:contains("Header")'
)
expect
(
doc
).
to
have_selector
(
'th:contains("Row")'
)
expect
(
doc
).
to
have_selector
(
'th:contains("Example")'
)
end
end
it
'allows Markdown in tables'
do
expect
(
@
doc
.
at_css
(
'td:contains("Baz")'
).
children
.
to_html
).
expect
(
doc
.
at_css
(
'td:contains("Baz")'
).
children
.
to_html
).
to
eq
'<strong>Baz</strong>'
end
end
describe
'Fenced Code Blocks'
do
it
'parses fenced code blocks'
do
expect
(
@doc
).
to
have_selector
(
'pre.code.highlight.white.c'
)
expect
(
@doc
).
to
have_selector
(
'pre.code.highlight.white.python'
)
aggregate_failures
do
expect
(
doc
).
to
have_selector
(
'pre.code.highlight.white.c'
)
expect
(
doc
).
to
have_selector
(
'pre.code.highlight.white.python'
)
end
end
describe
'Strikethrough'
do
it
'parses strikethroughs'
do
expect
(
@doc
).
to
have_selector
(
%{del:contains("and this text doesn't")}
)
end
expect
(
doc
).
to
have_selector
(
%{del:contains("and this text doesn't")}
)
end
describe
'Superscript'
do
it
'parses superscript'
do
body
=
get_section
(
'superscript'
)
expect
(
body
.
to_html
).
to
match
(
'1<sup>st</sup>'
)
expect
(
body
.
to_html
).
to
match
(
'2<sup>nd</sup>'
)
end
expect
(
doc
).
to
have_selector
(
'sup'
,
count:
2
)
end
end
describe
'HTML::Pipeline'
do
describe
'SanitizationFilter'
do
it
'uses a permissive whitelist'
do
expect
(
@doc
).
to
have_selector
(
'b:contains("b tag")'
)
expect
(
@doc
).
to
have_selector
(
'em:contains("em tag")'
)
expect
(
@doc
).
to
have_selector
(
'code:contains("code tag")'
)
expect
(
@doc
).
to
have_selector
(
'kbd:contains("s")'
)
expect
(
@doc
).
to
have_selector
(
'strike:contains(Emoji)'
)
expect
(
@doc
).
to
have_selector
(
'img[src*="smile.png"]'
)
expect
(
@doc
).
to
have_selector
(
'br'
)
expect
(
@doc
).
to
have_selector
(
'hr'
)
it
'permits b elements'
do
expect
(
doc
).
to
have_selector
(
'b:contains("b tag")'
)
end
it
'permits
span
elements'
do
expect
(
@doc
).
to
have_selector
(
'span:contains("span
tag")'
)
it
'permits
em
elements'
do
expect
(
doc
).
to
have_selector
(
'em:contains("em
tag")'
)
end
it
'permits table alignment'
do
expect
(
@doc
.
at_css
(
'th:contains("Header")'
)[
'style'
]).
to
eq
'text-align: center'
expect
(
@doc
.
at_css
(
'th:contains("Row")'
)[
'style'
]).
to
eq
'text-align: right'
expect
(
@doc
.
at_css
(
'th:contains("Example")'
)[
'style'
]).
to
eq
'text-align: left'
expect
(
@doc
.
at_css
(
'td:contains("Foo")'
)[
'style'
]).
to
eq
'text-align: center'
expect
(
@doc
.
at_css
(
'td:contains("Bar")'
)[
'style'
]).
to
eq
'text-align: right'
expect
(
@doc
.
at_css
(
'td:contains("Baz")'
)[
'style'
]).
to
eq
'text-align: left'
it
'permits code elements'
do
expect
(
doc
).
to
have_selector
(
'code:contains("code tag")'
)
end
it
'removes `rel` attribute from links'
do
body
=
get_section
(
'sanitizationfilter'
)
expect
(
body
).
not_to
have_selector
(
'a[rel="bookmark"]'
)
it
'permits kbd elements'
do
expect
(
doc
).
to
have_selector
(
'kbd:contains("s")'
)
end
it
"removes `href` from `a` elements if it's fishy"
do
expect
(
@doc
).
not_to
have_selector
(
'a[href*="javascript"]'
)
end
it
'permits strike elements'
do
expect
(
doc
).
to
have_selector
(
'strike:contains(Emoji)'
)
end
describe
'Escaping'
do
let
(
:table
)
{
@doc
.
css
(
'table'
).
last
.
at_css
(
'tbody'
)
}
it
'escapes non-tag angle brackets'
do
expect
(
table
.
at_xpath
(
'.//tr[1]/td[3]'
).
inner_html
).
to
eq
'1 < 3 & 5'
end
it
'permits img elements'
do
expect
(
doc
).
to
have_selector
(
'img[src*="smile.png"]'
)
end
describe
'Edge Cases'
do
it
'allows markup inside link elements'
do
expect
(
@doc
.
at_css
(
'a[href="#link-emphasis"]'
).
to_html
).
to
eq
%{<a href="#link-emphasis"><em>text</em></a>}
expect
(
@doc
.
at_css
(
'a[href="#link-strong"]'
).
to_html
).
to
eq
%{<a href="#link-strong"><strong>text</strong></a>}
it
'permits br elements'
do
expect
(
doc
).
to
have_selector
(
'br'
)
end
expect
(
@doc
.
at_css
(
'a[href="#link-code"]'
).
to_html
).
to
eq
%{<a href="#link-code"><code>text</code></a>}
it
'permits hr elements'
do
expect
(
doc
).
to
have_selector
(
'hr'
)
end
it
'permits span elements'
do
expect
(
doc
).
to
have_selector
(
'span:contains("span tag")'
)
end
describe
'EmojiFilter'
do
it
'parses Emoji'
do
expect
(
@doc
).
to
have_selector
(
'img.emoji'
,
count:
10
)
it
'permits style attribute in th elements'
do
aggregate_failures
do
expect
(
doc
.
at_css
(
'th:contains("Header")'
)[
'style'
]).
to
eq
'text-align: center'
expect
(
doc
.
at_css
(
'th:contains("Row")'
)[
'style'
]).
to
eq
'text-align: right'
expect
(
doc
.
at_css
(
'th:contains("Example")'
)[
'style'
]).
to
eq
'text-align: left'
end
end
describe
'TableOfContentsFilter
'
do
it
'creates anchors inside header elements'
do
expect
(
@doc
).
to
have_selector
(
'h1 a#gitlab-markdown'
)
expect
(
@doc
).
to
have_selector
(
'h2 a#markdown'
)
expect
(
@doc
).
to
have_selector
(
'h3 a#autolinkfilter'
)
it
'permits style attribute in td elements
'
do
aggregate_failures
do
expect
(
doc
.
at_css
(
'td:contains("Foo")'
)[
'style'
]).
to
eq
'text-align: center'
expect
(
doc
.
at_css
(
'td:contains("Bar")'
)[
'style'
]).
to
eq
'text-align: right'
expect
(
doc
.
at_css
(
'td:contains("Baz")'
)[
'style'
]).
to
eq
'text-align: left'
end
end
describe
'AutolinkFilter'
do
let
(
:list
)
{
get_section
(
'autolinkfilter'
).
next_element
}
def
item
(
index
)
list
.
at_css
(
"li:nth-child(
#{
index
}
)"
)
it
'removes `rel` attribute from links'
do
expect
(
doc
).
not_to
have_selector
(
'a[rel="bookmark"]'
)
end
it
'autolinks http://'
do
expect
(
item
(
1
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
1
).
children
.
first
[
'href'
]).
to
eq
'http://about.gitlab.com/'
it
"removes `href` from `a` elements if it's fishy"
do
expect
(
doc
).
not_to
have_selector
(
'a[href*="javascript"]'
)
end
it
'autolinks https://'
do
expect
(
item
(
2
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
2
).
children
.
first
[
'href'
]).
to
eq
'https://google.com/'
end
it
'autolinks ftp://'
do
expect
(
item
(
3
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
3
).
children
.
first
[
'href'
]).
to
eq
'ftp://ftp.us.debian.org/debian/'
describe
'Escaping'
do
it
'escapes non-tag angle brackets'
do
table
=
doc
.
css
(
'table'
).
last
.
at_css
(
'tbody'
)
expect
(
table
.
at_xpath
(
'.//tr[1]/td[3]'
).
inner_html
).
to
eq
'1 < 3 & 5'
end
it
'autolinks smb://'
do
expect
(
item
(
4
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
4
).
children
.
first
[
'href'
]).
to
eq
'smb://foo/bar/baz'
end
it
'autolinks irc://'
do
expect
(
item
(
5
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
5
).
children
.
first
[
'href'
]).
to
eq
'irc://irc.freenode.net/git'
end
describe
'Edge Cases'
do
it
'allows markup inside link elements'
do
aggregate_failures
do
expect
(
doc
.
at_css
(
'a[href="#link-emphasis"]'
).
to_html
).
to
eq
%{<a href="#link-emphasis"><em>text</em></a>}
it
'autolinks short, invalid URLs'
do
expect
(
item
(
6
).
children
.
first
.
name
).
to
eq
'a'
expect
(
item
(
6
).
children
.
first
[
'href'
]).
to
eq
'http://localhost:3000'
end
expect
(
doc
.
at_css
(
'a[href="#link-strong"]'
).
to_html
).
to
eq
%{<a href="#link-strong"><strong>text</strong></a>}
%w(code a kbd)
.
each
do
|
elem
|
it
"ignores links inside '
#{
elem
}
' element"
do
body
=
get_section
(
'autolinkfilter'
)
expect
(
body
).
not_to
have_selector
(
"
#{
elem
}
a"
)
expect
(
doc
.
at_css
(
'a[href="#link-code"]'
).
to_html
).
to
eq
%{<a href="#link-code"><code>text</code></a>}
end
end
end
describe
'ExternalLinkFilter'
do
let
(
:links
)
{
get_section
(
'externallinkfilter'
).
next_element
}
it
'adds nofollow to external link'
do
expect
(
links
.
css
(
'a'
).
first
.
to_html
).
to
match
'nofollow'
link
=
doc
.
at_css
(
'a:contains("Google")'
)
expect
(
link
.
attr
(
'rel'
)).
to
match
'nofollow'
end
it
'ignores internal link'
do
expect
(
links
.
css
(
'a'
).
last
.
to_html
).
not_to
match
'nofollow'
link
=
doc
.
at_css
(
'a:contains("GitLab Root")'
)
expect
(
link
.
attr
(
'rel'
)).
not_to
match
'nofollow'
end
end
describe
'ReferenceFilter'
do
it
'handles references in headers'
do
header
=
@doc
.
at_css
(
'#reference-filters-eg-1'
).
parent
expect
(
header
.
css
(
'a'
).
size
).
to
eq
2
end
it
"handles references in Markdown"
do
body
=
get_section
(
'reference-filters-eg-1'
)
expect
(
body
).
to
have_selector
(
'em a.gfm-merge_request'
,
count:
1
)
end
it
'parses user references'
do
body
=
get_section
(
'userreferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-project_member'
,
count:
3
)
end
it
'parses issue references'
do
body
=
get_section
(
'issuereferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-issue'
,
count:
2
)
end
it
'parses merge request references'
do
body
=
get_section
(
'mergerequestreferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-merge_request'
,
count:
2
)
end
it
'parses snippet references'
do
body
=
get_section
(
'snippetreferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-snippet'
,
count:
2
)
end
it
'parses commit range references'
do
body
=
get_section
(
'commitrangereferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-commit_range'
,
count:
2
)
end
it
'parses commit references'
do
body
=
get_section
(
'commitreferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-commit'
,
count:
2
)
end
it
'parses label references'
do
body
=
get_section
(
'labelreferencefilter'
)
expect
(
body
).
to
have_selector
(
'a.gfm.gfm-label'
,
count:
3
)
end
end
describe
'Task Lists'
do
it
'generates task lists'
do
body
=
get_section
(
'task-lists'
)
expect
(
body
).
to
have_selector
(
'ul.task-list'
,
count:
2
)
expect
(
body
).
to
have_selector
(
'li.task-list-item'
,
count:
7
)
expect
(
body
).
to
have_selector
(
'input[checked]'
,
count:
3
)
end
end
end
end
# This is a helper class used by the GitLab Markdown feature spec
#
# Because the feature spec only cares about the output of the Markdown, and the
# test setup and teardown and parsing is fairly expensive, we only want to do it
# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)`
# block, so we fake it by encapsulating all the shared setup in this class.
#
# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for
# reference to the factory-created objects.
class
MarkdownFeature
include
FactoryGirl
::
Syntax
::
Methods
def
initialize
DatabaseCleaner
.
start
end
def
teardown
DatabaseCleaner
.
clean
end
def
user
@user
||=
create
(
:user
)
end
def
group
unless
@group
@group
=
create
(
:group
)
@group
.
add_user
(
user
,
Gitlab
::
Access
::
DEVELOPER
)
end
@group
end
# Direct references ----------------------------------------------------------
def
project
@project
||=
create
(
:project
)
end
def
issue
@issue
||=
create
(
:issue
,
project:
project
)
end
def
merge_request
@merge_request
||=
create
(
:merge_request
,
:simple
,
source_project:
project
)
end
def
snippet
@snippet
||=
create
(
:project_snippet
,
project:
project
)
end
def
commit
@commit
||=
project
.
commit
end
context
'default pipeline'
do
before
(
:all
)
do
@feat
=
MarkdownFeature
.
new
def
commit_range
unless
@commit_range
commit2
=
project
.
commit
(
'HEAD~3'
)
@commit_range
=
CommitRange
.
new
(
"
#{
commit
.
id
}
...
#{
commit2
.
id
}
"
,
project
)
end
# `gfm_with_options` depends on a `@project` variable
@project
=
@feat
.
project
@commit_range
@html
=
markdown
(
@feat
.
raw_markdown
)
end
def
simple_label
@simple_label
||=
create
(
:label
,
name:
'gfm'
,
project:
project
)
end
it_behaves_like
'all pipelines'
def
label
@label
||=
create
(
:label
,
name:
'awaiting feedback'
,
project:
project
)
it
'includes RelativeLinkFilter'
do
expect
(
doc
).
to
parse_relative_links
end
# Cross-references -----------------------------------------------------------
def
xproject
unless
@xproject
namespace
=
create
(
:namespace
,
name:
'cross-reference'
)
@xproject
=
create
(
:project
,
namespace:
namespace
)
@xproject
.
team
<<
[
user
,
:developer
]
it
'includes EmojiFilter'
do
expect
(
doc
).
to
parse_emoji
end
@xproject
it
'includes TableOfContentsFilter'
do
expect
(
doc
).
to
create_header_links
end
def
xissue
@xissue
||=
create
(
:issue
,
project:
xproject
)
it
'includes AutolinkFilter'
do
expect
(
doc
).
to
create_autolinks
end
def
xmerge_request
@xmerge_request
||=
create
(
:merge_request
,
:simple
,
source_project:
xproject
)
it
'includes all reference filters'
do
aggregate_failures
do
expect
(
doc
).
to
reference_users
expect
(
doc
).
to
reference_issues
expect
(
doc
).
to
reference_merge_requests
expect
(
doc
).
to
reference_snippets
expect
(
doc
).
to
reference_commit_ranges
expect
(
doc
).
to
reference_commits
expect
(
doc
).
to
reference_labels
end
def
xsnippet
@xsnippet
||=
create
(
:project_snippet
,
project:
xproject
)
end
def
xcommit
@xcommit
||=
xproject
.
commit
it
'includes TaskListFilter'
do
expect
(
doc
).
to
parse_task_lists
end
def
xcommit_range
unless
@xcommit_range
xcommit2
=
xproject
.
commit
(
'HEAD~2'
)
@xcommit_range
=
CommitRange
.
new
(
"
#{
xcommit
.
id
}
...
#{
xcommit2
.
id
}
"
,
xproject
)
end
@xcommit_range
# `markdown` calls these two methods
def
current_user
@feat
.
user
end
def
raw_markdown
fixture
=
Rails
.
root
.
join
(
'spec/fixtures/markdown.md.erb'
)
ERB
.
new
(
File
.
read
(
fixture
)).
result
(
binding
)
def
user_color_scheme_class
:white
end
end
spec/fixtures/markdown.md.erb
View file @
be25f261
...
...
@@ -100,6 +100,13 @@ Markdown should be usable inside a link. Let's try!
- [**text**](#link-strong)
- [`text`](#link-code)
### RelativeLinkFilter
Linking to a file relative to this project's repository should work.
[Relative Link](doc/README.md)
![Relative Image](app/assets/images/touch-icon-ipad.png)
### EmojiFilter
Because life would be :zzz: without Emoji, right? :rocket:
...
...
@@ -123,9 +130,9 @@ These are all plain text that should get turned into links:
But it shouldn't autolink text inside certain tags:
-
<code>
http://
about
.gitlab.com/
</code>
-
<a>
http://a
bout
.gitlab.com/
</a>
-
<kbd>
http://
about
.gitlab.com/
</kbd>
-
<code>
http://
code
.gitlab.com/
</code>
-
<a>
http://a.gitlab.com/
</a>
-
<kbd>
http://
kbd
.gitlab.com/
</kbd>
### ExternalLinkFilter
...
...
spec/lib/gitlab/markdown/relative_link_filter_spec.rb
View file @
be25f261
# encoding: UTF-8
require
'spec_helper'
module
Gitlab::Markdown
...
...
@@ -101,6 +103,20 @@ module Gitlab::Markdown
expect
(
doc
.
at_css
(
'a'
)[
'href'
]).
to
eq
'http://example.com'
end
it
'supports Unicode filenames'
do
path
=
'files/images/한글.png'
escaped
=
Addressable
::
URI
.
escape
(
path
)
# Stub these methods so the file doesn't actually need to be in the repo
allow_any_instance_of
(
described_class
).
to
receive
(
:file_exists?
).
and_return
(
true
)
allow_any_instance_of
(
described_class
).
to
receive
(
:image?
).
with
(
path
).
and_return
(
true
)
doc
=
filter
(
image
(
escaped
))
expect
(
doc
.
at_css
(
'img'
)[
'src'
]).
to
match
'/raw/'
end
context
'when requested path is a file in the repo'
do
let
(
:requested_path
)
{
'doc/api/README.md'
}
include_examples
:relative_to_requested
...
...
spec/models/project_spec.rb
View file @
be25f261
...
...
@@ -111,14 +111,20 @@ describe Project do
expect
(
project
.
url_to_repo
).
to
eq
(
Gitlab
.
config
.
gitlab_shell
.
ssh_path_prefix
+
'somewhere.git'
)
end
describe
"#web_url"
do
let
(
:project
)
{
create
(
:empty_project
,
path:
"somewhere"
)
}
it
'returns the full web URL for this repo'
do
project
=
Project
.
new
(
path:
'somewhere'
)
e
xpect
(
project
.
web_url
).
to
eq
(
"
#{
Gitlab
.
config
.
gitlab
.
url
}
/somewhere"
)
expect
(
project
.
web_url
).
to
eq
(
"
#{
Gitlab
.
config
.
gitlab
.
url
}
/
#{
project
.
namespace
.
path
}
/somewhere"
)
e
nd
end
describe
"#web_url_without_protocol"
do
let
(
:project
)
{
create
(
:empty_project
,
path:
"somewhere"
)
}
it
'returns the web URL without the protocol for this repo'
do
project
=
Project
.
new
(
path:
'somewhere'
)
e
xpect
(
project
.
web_url_without_protocol
).
to
eq
(
"
#{
Gitlab
.
config
.
gitlab
.
url
.
split
(
'://'
)[
1
]
}
/somewhere"
)
expect
(
project
.
web_url_without_protocol
).
to
eq
(
"
#{
Gitlab
.
config
.
gitlab
.
url
.
split
(
'://'
)[
1
]
}
/
#{
project
.
namespace
.
path
}
/somewhere"
)
e
nd
end
describe
'last_activity methods'
do
...
...
spec/support/markdown_feature.rb
0 → 100644
View file @
be25f261
# This is a helper class used by the GitLab Markdown feature spec
#
# Because the feature spec only cares about the output of the Markdown, and the
# test setup and teardown and parsing is fairly expensive, we only want to do it
# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)`
# block, so we fake it by encapsulating all the shared setup in this class.
#
# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for
# reference to the factory-created objects.
class
MarkdownFeature
include
FactoryGirl
::
Syntax
::
Methods
def
user
@user
||=
create
(
:user
)
end
def
group
unless
@group
@group
=
create
(
:group
)
@group
.
add_user
(
user
,
Gitlab
::
Access
::
DEVELOPER
)
end
@group
end
# Direct references ----------------------------------------------------------
def
project
@project
||=
create
(
:project
)
end
def
issue
@issue
||=
create
(
:issue
,
project:
project
)
end
def
merge_request
@merge_request
||=
create
(
:merge_request
,
:simple
,
source_project:
project
)
end
def
snippet
@snippet
||=
create
(
:project_snippet
,
project:
project
)
end
def
commit
@commit
||=
project
.
commit
end
def
commit_range
unless
@commit_range
commit2
=
project
.
commit
(
'HEAD~3'
)
@commit_range
=
CommitRange
.
new
(
"
#{
commit
.
id
}
...
#{
commit2
.
id
}
"
,
project
)
end
@commit_range
end
def
simple_label
@simple_label
||=
create
(
:label
,
name:
'gfm'
,
project:
project
)
end
def
label
@label
||=
create
(
:label
,
name:
'awaiting feedback'
,
project:
project
)
end
# Cross-references -----------------------------------------------------------
def
xproject
unless
@xproject
namespace
=
create
(
:namespace
,
name:
'cross-reference'
)
@xproject
=
create
(
:project
,
namespace:
namespace
)
@xproject
.
team
<<
[
user
,
:developer
]
end
@xproject
end
def
xissue
@xissue
||=
create
(
:issue
,
project:
xproject
)
end
def
xmerge_request
@xmerge_request
||=
create
(
:merge_request
,
:simple
,
source_project:
xproject
)
end
def
xsnippet
@xsnippet
||=
create
(
:project_snippet
,
project:
xproject
)
end
def
xcommit
@xcommit
||=
xproject
.
commit
end
def
xcommit_range
unless
@xcommit_range
xcommit2
=
xproject
.
commit
(
'HEAD~2'
)
@xcommit_range
=
CommitRange
.
new
(
"
#{
xcommit
.
id
}
...
#{
xcommit2
.
id
}
"
,
xproject
)
end
@xcommit_range
end
def
raw_markdown
fixture
=
Rails
.
root
.
join
(
'spec/fixtures/markdown.md.erb'
)
ERB
.
new
(
File
.
read
(
fixture
)).
result
(
binding
)
end
end
spec/support/matchers/markdown_matchers.rb
0 → 100644
View file @
be25f261
# MarkdownMatchers
#
# Custom matchers for our custom HTML::Pipeline filters. These are used to test
# that specific filters are or are not used by our defined pipelines.
#
# Must be included manually.
module
MarkdownMatchers
extend
RSpec
::
Matchers
::
DSL
include
Capybara
::
Node
::
Matchers
# RelativeLinkFilter
matcher
:parse_relative_links
do
set_default_markdown_messages
match
do
|
actual
|
link
=
actual
.
at_css
(
'a:contains("Relative Link")'
)
image
=
actual
.
at_css
(
'img[alt="Relative Image"]'
)
expect
(
link
[
'href'
]).
to
end_with
(
'master/doc/README.md'
)
expect
(
image
[
'src'
]).
to
end_with
(
'master/app/assets/images/touch-icon-ipad.png'
)
end
end
# EmojiFilter
matcher
:parse_emoji
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'img.emoji'
,
count:
10
)
end
end
# TableOfContentsFilter
matcher
:create_header_links
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'h1 a#gitlab-markdown'
)
expect
(
actual
).
to
have_selector
(
'h2 a#markdown'
)
expect
(
actual
).
to
have_selector
(
'h3 a#autolinkfilter'
)
end
end
# AutolinkFilter
matcher
:create_autolinks
do
def
have_autolink
(
link
)
have_link
(
link
,
href:
link
)
end
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_autolink
(
'http://about.gitlab.com/'
)
expect
(
actual
).
to
have_autolink
(
'https://google.com/'
)
expect
(
actual
).
to
have_autolink
(
'ftp://ftp.us.debian.org/debian/'
)
expect
(
actual
).
to
have_autolink
(
'smb://foo/bar/baz'
)
expect
(
actual
).
to
have_autolink
(
'irc://irc.freenode.net/git'
)
expect
(
actual
).
to
have_autolink
(
'http://localhost:3000'
)
%w(code a kbd)
.
each
do
|
elem
|
expect
(
body
).
not_to
have_selector
(
"
#{
elem
}
a"
)
end
end
end
# UserReferenceFilter
matcher
:reference_users
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-project_member'
,
count:
3
)
end
end
# IssueReferenceFilter
matcher
:reference_issues
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-issue'
,
count:
3
)
end
end
# MergeRequestReferenceFilter
matcher
:reference_merge_requests
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-merge_request'
,
count:
3
)
expect
(
actual
).
to
have_selector
(
'em a.gfm-merge_request'
)
end
end
# SnippetReferenceFilter
matcher
:reference_snippets
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-snippet'
,
count:
2
)
end
end
# CommitRangeReferenceFilter
matcher
:reference_commit_ranges
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-commit_range'
,
count:
2
)
end
end
# CommitReferenceFilter
matcher
:reference_commits
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-commit'
,
count:
2
)
end
end
# LabelReferenceFilter
matcher
:reference_labels
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'a.gfm.gfm-label'
,
count:
3
)
end
end
# TaskListFilter
matcher
:parse_task_lists
do
set_default_markdown_messages
match
do
|
actual
|
expect
(
actual
).
to
have_selector
(
'ul.task-list'
,
count:
2
)
expect
(
actual
).
to
have_selector
(
'li.task-list-item'
,
count:
7
)
expect
(
actual
).
to
have_selector
(
'input[checked]'
,
count:
3
)
end
end
end
# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for
# setting the failure messages for these matchers
module
RSpec::Matchers::DSL::Macros
def
set_default_markdown_messages
failure_message
do
# expected to parse emoji, but didn't
"expected to
#{
description
}
, but didn't"
end
failure_message_when_negated
do
# expected not to parse task lists, but did
"expected not to
#{
description
}
, but did"
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment