Commit 1b69145d authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'ce-to-ee-2018-09-06' into 'master'

CE upstream - 2018-09-06 09:22 UTC

See merge request gitlab-org/gitlab-ee!7264
parents 5e741e4c 8dbb497a
...@@ -71,7 +71,7 @@ gem 'u2f', '~> 0.2.1' ...@@ -71,7 +71,7 @@ gem 'u2f', '~> 0.2.1'
gem 'validates_hostname', '~> 1.0.6' gem 'validates_hostname', '~> 1.0.6'
# Browser detection # Browser detection
gem 'browser', '~> 2.2' gem 'browser', '~> 2.5'
# GPG # GPG
gem 'gpgme' gem 'gpgme'
......
...@@ -98,7 +98,7 @@ GEM ...@@ -98,7 +98,7 @@ GEM
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap_form (2.7.0) bootstrap_form (2.7.0)
brakeman (4.2.1) brakeman (4.2.1)
browser (2.2.0) browser (2.5.3)
builder (3.2.3) builder (3.2.3)
bullet (5.5.1) bullet (5.5.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
...@@ -1021,7 +1021,7 @@ DEPENDENCIES ...@@ -1021,7 +1021,7 @@ DEPENDENCIES
bootsnap (~> 1.3) bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0) bootstrap_form (~> 2.7.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 2.2) browser (~> 2.5)
bullet (~> 5.5.0) bullet (~> 5.5.0)
bundler-audit (~> 0.5.0) bundler-audit (~> 0.5.0)
capybara (~> 2.15) capybara (~> 2.15)
......
...@@ -101,7 +101,7 @@ GEM ...@@ -101,7 +101,7 @@ GEM
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap_form (2.7.0) bootstrap_form (2.7.0)
brakeman (4.2.1) brakeman (4.2.1)
browser (2.2.0) browser (2.5.3)
builder (3.2.3) builder (3.2.3)
bullet (5.5.1) bullet (5.5.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
...@@ -1030,7 +1030,7 @@ DEPENDENCIES ...@@ -1030,7 +1030,7 @@ DEPENDENCIES
bootsnap (~> 1.3) bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0) bootstrap_form (~> 2.7.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 2.2) browser (~> 2.5)
bullet (~> 5.5.0) bullet (~> 5.5.0)
bundler-audit (~> 0.5.0) bundler-audit (~> 0.5.0)
capybara (~> 2.15) capybara (~> 2.15)
......
...@@ -110,6 +110,7 @@ class ApplicationController < ActionController::Base ...@@ -110,6 +110,7 @@ class ApplicationController < ActionController::Base
def append_info_to_payload(payload) def append_info_to_payload(payload)
super super
payload[:ua] = request.env["HTTP_USER_AGENT"]
payload[:remote_ip] = request.remote_ip payload[:remote_ip] = request.remote_ip
logged_user = auth_user logged_user = auth_user
......
...@@ -107,23 +107,23 @@ module MarkupHelper ...@@ -107,23 +107,23 @@ module MarkupHelper
def markup(file_name, text, context = {}) def markup(file_name, text, context = {})
context[:project] ||= @project context[:project] ||= @project
context[:markdown_engine] ||= :redcarpet context[:markdown_engine] ||= :redcarpet unless commonmark_for_repositories_enabled?
html = context.delete(:rendered) || markup_unsafe(file_name, text, context) html = context.delete(:rendered) || markup_unsafe(file_name, text, context)
prepare_for_rendering(html, context) prepare_for_rendering(html, context)
end end
def render_wiki_content(wiki_page) def render_wiki_content(wiki_page, context = {})
text = wiki_page.content text = wiki_page.content
return '' unless text.present? return '' unless text.present?
context = { context.merge!(
pipeline: :wiki, pipeline: :wiki,
project: @project, project: @project,
project_wiki: @project_wiki, project_wiki: @project_wiki,
page_slug: wiki_page.slug, page_slug: wiki_page.slug,
issuable_state_filter_enabled: true, issuable_state_filter_enabled: true
markdown_engine: :redcarpet )
} context[:markdown_engine] ||= :redcarpet unless commonmark_for_repositories_enabled?
html = html =
case wiki_page.format case wiki_page.format
...@@ -178,6 +178,10 @@ module MarkupHelper ...@@ -178,6 +178,10 @@ module MarkupHelper
end end
end end
def commonmark_for_repositories_enabled?
Feature.enabled?(:commonmark_for_repositories, default_enabled: true)
end
private private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML # Return +text+, truncated to +max_chars+ characters, excluding any HTML
......
...@@ -254,6 +254,10 @@ module ProjectsHelper ...@@ -254,6 +254,10 @@ module ProjectsHelper
"xcode://clone?repo=#{CGI.escape(default_url_to_repo(project))}" "xcode://clone?repo=#{CGI.escape(default_url_to_repo(project))}"
end end
def legacy_render_context(params)
params[:legacy_render] ? { markdown_engine: :redcarpet } : {}
end
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
......
...@@ -90,7 +90,9 @@ module Ci ...@@ -90,7 +90,9 @@ module Ci
end end
def hashed_path? def hashed_path?
super || self.try(:file_location).nil? return true if trace? # ArchiveLegacyTraces background migration might not have `file_location` column
super || self.file_location.nil?
end end
def expire_in def expire_in
......
...@@ -585,7 +585,12 @@ class Repository ...@@ -585,7 +585,12 @@ class Repository
end end
def rendered_readme def rendered_readme
MarkupHelper.markup_unsafe(readme.name, readme.data, project: project, markdown_engine: :redcarpet) if readme return unless readme
context = { project: project }
context[:markdown_engine] = :redcarpet unless MarkupHelper.commonmark_for_repositories_enabled?
MarkupHelper.markup_unsafe(readme.name, readme.data, context)
end end
cache_method :rendered_readme cache_method :rendered_readme
......
...@@ -43,6 +43,10 @@ class PreviewMarkdownService < BaseService ...@@ -43,6 +43,10 @@ class PreviewMarkdownService < BaseService
end end
def markdown_engine def markdown_engine
if params[:legacy_render]
:redcarpet
else
CacheMarkdownField::MarkdownEngine.from_version(params[:markdown_version].to_i) CacheMarkdownField::MarkdownEngine.from_version(params[:markdown_version].to_i)
end end
end
end end
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
%div{ class: container_class } %div{ class: container_class }
.prepend-top-default.append-bottom-default .prepend-top-default.append-bottom-default
.wiki .wiki
= render_wiki_content(@wiki_home) = render_wiki_content(@wiki_home, legacy_render_context(params))
- else - else
- can_create_wiki = can?(current_user, :create_wiki, @project) - can_create_wiki = can?(current_user, :create_wiki, @project)
.project-home-empty{ class: [('row-content-block' if can_create_wiki), ('content-block' unless can_create_wiki)] } .project-home-empty{ class: [('row-content-block' if can_create_wiki), ('content-block' unless can_create_wiki)] }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
Write Write
%li %li
= link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id, legacy_render: params[:legacy_render]) do
= editing_preview_title(@blob.name) = editing_preview_title(@blob.name)
= form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do = form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.diff-content .diff-content
- if markup?(@blob.name) - if markup?(@blob.name)
.file-content.wiki .file-content.wiki
= markup(@blob.name, @content) = markup(@blob.name, @content, legacy_render_context(params))
- else - else
.file-content.code.js-syntax-highlight .file-content.code.js-syntax-highlight
- unless @diff_lines.empty? - unless @diff_lines.empty?
......
- blob = viewer.blob - blob = viewer.blob
- rendered_markup = blob.rendered_markup if blob.respond_to?(:rendered_markup) - context = legacy_render_context(params)
- unless context[:markdown_engine] == :redcarpet
- context[:rendered] = blob.rendered_markup if blob.respond_to?(:rendered_markup)
.file-content.wiki .file-content.wiki
= markup(blob.name, blob.data, rendered: rendered_markup) = markup(blob.name, blob.data, context)
- commit_message = @page.persisted? ? s_("WikiPageEdit|Update %{page_title}") : s_("WikiPageCreate|Create %{page_title}") - commit_message = @page.persisted? ? s_("WikiPageEdit|Update %{page_title}") : s_("WikiPageCreate|Create %{page_title}")
- commit_message = commit_message % { page_title: @page.title } - commit_message = commit_message % { page_title: @page.title }
- if params[:legacy_render] || !commonmark_for_repositories_enabled?
- markdown_version = CacheMarkdownField::CACHE_REDCARPET_VERSION
- else
- markdown_version = 0
= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, = form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post,
html: { class: 'wiki-form common-note-form prepend-top-default js-quick-submit' }, html: { class: 'wiki-form common-note-form prepend-top-default js-quick-submit' },
data: { markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION } do |f| data: { markdown_version: markdown_version } do |f|
= form_errors(@page) = form_errors(@page)
- if @page.persisted? - if @page.persisted?
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
.blocks-container .blocks-container
.block.block-first .block.block-first
- if @sidebar_page - if @sidebar_page
= render_wiki_content(@sidebar_page) = render_wiki_content(@sidebar_page, legacy_render_context(params))
- else - else
%ul.wiki-pages %ul.wiki-pages
= render @sidebar_wiki_entries, context: 'sidebar' = render @sidebar_wiki_entries, context: 'sidebar'
......
...@@ -26,6 +26,6 @@ ...@@ -26,6 +26,6 @@
.prepend-top-default.append-bottom-default .prepend-top-default.append-bottom-default
.wiki .wiki
= render_wiki_content(@page) = render_wiki_content(@page, legacy_render_context(params))
= render 'sidebar' = render 'sidebar'
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
.file-content.wiki .file-content.wiki
- snippet_chunks.each do |chunk| - snippet_chunks.each do |chunk|
- unless chunk[:data].empty? - unless chunk[:data].empty?
= markup(snippet.file_name, chunk[:data]) = markup(snippet.file_name, chunk[:data], legacy_render_context(params))
- else - else
.file-content.code .file-content.code
.nothing-here-block Empty file .nothing-here-block Empty file
......
---
title: Render files (`.md`) and wikis using CommonMark
merge_request: 21228
author:
type: changed
---
title: Upgrade Monaco editor
merge_request:
author:
type: other
---
title: Explicit hashed path check for trace, prevents background migration from accessing
file_location column that doesn't exist
merge_request: 21533
author: Jasper Maes
type: other
---
title: Add User-Agent to production_json.log
merge_request: 21546
author:
type: other
...@@ -22,7 +22,8 @@ unless Sidekiq.server? ...@@ -22,7 +22,8 @@ unless Sidekiq.server?
params: params, params: params,
remote_ip: event.payload[:remote_ip], remote_ip: event.payload[:remote_ip],
user_id: event.payload[:user_id], user_id: event.payload[:user_id],
username: event.payload[:username] username: event.payload[:username],
ua: event.payload[:ua]
} }
gitaly_calls = Gitlab::GitalyClient.get_request_count gitaly_calls = Gitlab::GitalyClient.get_request_count
......
...@@ -58,6 +58,13 @@ Features that are developed and are intended to be merged behind a feature flag ...@@ -58,6 +58,13 @@ Features that are developed and are intended to be merged behind a feature flag
should not include a changelog entry. The entry should be added in the merge should not include a changelog entry. The entry should be added in the merge
request removing the feature flags. request removing the feature flags.
In the rare case that you need the feature flag to be on automatically, use
`default_enabled: true` when checking:
```ruby
Feature.enabled?(:feature_flag, project, default_enabled: true)
```
### Specs ### Specs
In the test environment `Feature.enabled?` is stubbed to always respond to `true`, In the test environment `Feature.enabled?` is stubbed to always respond to `true`,
......
...@@ -42,13 +42,21 @@ class Feature ...@@ -42,13 +42,21 @@ class Feature
persisted_names.include?(feature.name.to_s) persisted_names.include?(feature.name.to_s)
end end
def enabled?(key, thing = nil) # use `default_enabled: true` to default the flag to being `enabled`
get(key).enabled?(thing) # unless set explicitly. The default is `disabled`
def enabled?(key, thing = nil, default_enabled: false)
feature = Feature.get(key)
# If we're not default enabling the flag or the feature has been set, always evaluate.
# `persisted?` can potentially generate DB queries and also checks for inclusion
# in an array of feature names (177 at last count), possibly reducing performance by half.
# So we only perform the `persisted` check if `default_enabled: true`
!default_enabled || Feature.persisted?(feature) ? feature.enabled?(thing) : true
end end
def disabled?(key, thing = nil) def disabled?(key, thing = nil, default_enabled: false)
# we need to make different method calls to make it easy to mock / define expectations in test mode # we need to make different method calls to make it easy to mock / define expectations in test mode
thing.nil? ? !enabled?(key) : !enabled?(key, thing) thing.nil? ? !enabled?(key, default_enabled: default_enabled) : !enabled?(key, thing, default_enabled: default_enabled)
end end
def enable(key, thing = true) def enable(key, thing = true)
......
...@@ -77,7 +77,8 @@ module RuboCop ...@@ -77,7 +77,8 @@ module RuboCop
start_clause_line?(previous_line(node)) || start_clause_line?(previous_line(node)) ||
block_start?(previous_line(node)) || block_start?(previous_line(node)) ||
begin_line?(previous_line(node)) || begin_line?(previous_line(node)) ||
assignment_line?(previous_line(node)) assignment_line?(previous_line(node)) ||
rescue_line?(previous_line(node))
end end
def last_line_valid?(node) def last_line_valid?(node)
...@@ -111,6 +112,10 @@ module RuboCop ...@@ -111,6 +112,10 @@ module RuboCop
line =~ /^\s*.*=/ line =~ /^\s*.*=/
end end
def rescue_line?(line)
line =~ /^\s*rescue/
end
def block_start?(line) def block_start?(line)
line.match(/ (do|{)( \|.*?\|)?\s?$/) line.match(/ (do|{)( \|.*?\|)?\s?$/)
end end
......
...@@ -5,8 +5,8 @@ describe 'File blob', :js do ...@@ -5,8 +5,8 @@ describe 'File blob', :js do
let(:project) { create(:project, :public, :repository) } let(:project) { create(:project, :public, :repository) }
def visit_blob(path, anchor: nil, ref: 'master') def visit_blob(path, anchor: nil, ref: 'master', legacy_render: nil)
visit project_blob_path(project, File.join(ref, path), anchor: anchor) visit project_blob_path(project, File.join(ref, path), anchor: anchor, legacy_render: legacy_render)
wait_for_requests wait_for_requests
end end
...@@ -142,6 +142,52 @@ describe 'File blob', :js do ...@@ -142,6 +142,52 @@ describe 'File blob', :js do
end end
end end
context 'Markdown rendering' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add RedCarpet and CommonMark Markdown ",
file_path: 'files/commonmark/file.md',
file_content: "1. one\n - sublist\n"
).execute
end
context 'when rendering default markdown' do
before do
visit_blob('files/commonmark/file.md')
wait_for_requests
end
it 'renders using CommonMark' do
aggregate_failures do
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
end
end
context 'when rendering legacy markdown' do
before do
visit_blob('files/commonmark/file.md', legacy_render: 1)
wait_for_requests
end
it 'renders using RedCarpet' do
aggregate_failures do
expect(page).to have_content("sublist")
expect(page).to have_xpath("//ol//li//ul")
end
end
end
end
context 'Markdown file (stored in LFS)' do context 'Markdown file (stored in LFS)' do
before do before do
project.add_maintainer(project.creator) project.add_maintainer(project.creator)
......
...@@ -7,6 +7,7 @@ describe 'Editing file blob', :js do ...@@ -7,6 +7,7 @@ describe 'Editing file blob', :js do
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') } let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
let(:branch) { 'master' } let(:branch) { 'master' }
let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] } let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
let(:readme_file_path) { 'README.md' }
context 'as a developer' do context 'as a developer' do
let(:user) { create(:user) } let(:user) { create(:user) }
...@@ -20,14 +21,19 @@ describe 'Editing file blob', :js do ...@@ -20,14 +21,19 @@ describe 'Editing file blob', :js do
def edit_and_commit(commit_changes: true) def edit_and_commit(commit_changes: true)
wait_for_requests wait_for_requests
find('.js-edit-blob').click find('.js-edit-blob').click
find('#editor') fill_editor(content: "class NextFeature\\nend\\n")
execute_script('ace.edit("editor").setValue("class NextFeature\nend\n")')
if commit_changes if commit_changes
click_button 'Commit changes' click_button 'Commit changes'
end end
end end
def fill_editor(content: "class NextFeature\\nend\\n")
wait_for_requests
find('#editor')
execute_script("ace.edit('editor').setValue('#{content}')")
end
context 'from MR diff' do context 'from MR diff' do
before do before do
visit diffs_project_merge_request_path(project, merge_request) visit diffs_project_merge_request_path(project, merge_request)
...@@ -63,6 +69,30 @@ describe 'Editing file blob', :js do ...@@ -63,6 +69,30 @@ describe 'Editing file blob', :js do
expect(new_line_count).to be > 0 expect(new_line_count).to be > 0
end end
end end
context 'when rendering the preview' do
it 'renders content with CommonMark' do
visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
fill_editor(content: "1. one\\n - sublist\\n")
click_link 'Preview'
wait_for_requests
# the above generates two seperate lists (not embedded) in CommonMark
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
it 'renders content with RedCarpet when legacy_render is set' do
visit project_edit_blob_path(project, tree_join(branch, readme_file_path), legacy_render: 1)
fill_editor(content: "1. one\\n - sublist\\n")
click_link 'Preview'
wait_for_requests
# the above generates a sublist list in RedCarpet
expect(page).to have_content("sublist")
expect(page).to have_xpath("//ol//li//ul")
end
end
end end
context 'visit blob edit' do context 'visit blob edit' do
......
...@@ -162,6 +162,34 @@ describe 'Projects > Wiki > User previews markdown changes', :js do ...@@ -162,6 +162,34 @@ describe 'Projects > Wiki > User previews markdown changes', :js do
expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
end end
end end
context 'when rendering the preview' do
it 'renders content with CommonMark' do
create_wiki_page 'a-page/b-page/c-page/common-mark'
click_link 'Edit'
fill_in :wiki_content, with: "1. one\n - sublist\n"
click_on "Preview"
# the above generates two seperate lists (not embedded) in CommonMark
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
it 'renders content with RedCarpet when legacy_render is set' do
wiki_page = create(:wiki_page,
wiki: project.wiki,
attrs: { title: 'home', content: "Empty content" })
visit(project_wiki_edit_path(project, wiki_page, legacy_render: 1))
fill_in :wiki_content, with: "1. one\n - sublist\n"
click_on "Preview"
# the above generates a sublist list in RedCarpet
expect(page).to have_content("sublist")
expect(page).to have_xpath("//ol//li//ul")
end
end
end end
it "does not linkify double brackets inside code blocks as expected" do it "does not linkify double brackets inside code blocks as expected" do
......
...@@ -68,26 +68,48 @@ describe 'Snippet', :js do ...@@ -68,26 +68,48 @@ describe 'Snippet', :js do
end end
end end
context 'with cached Redcarpet html' do context 'Markdown rendering' do
let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION) } let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content) }
let(:file_name) { 'test.md' } let(:file_name) { 'test.md' }
let(:content) { "1. one\n - sublist\n" } let(:content) { "1. one\n - sublist\n" }
it 'renders correctly' do context 'when rendering default markdown' do
it 'renders using CommonMark' do
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
end
context 'when rendering legacy markdown' do
before do
visit snippet_path(snippet, legacy_render: 1)
wait_for_requests
end
it 'renders using RedCarpet' do
expect(page).to have_content("sublist")
expect(page).to have_xpath("//ol//li//ul") expect(page).to have_xpath("//ol//li//ul")
end end
end end
context 'with cached CommonMark html' do context 'with cached CommonMark html' do
let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION) } let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
let(:file_name) { 'test.md' }
let(:content) { "1. one\n - sublist\n" }
it 'renders correctly' do it 'renders correctly' do
expect(page).not_to have_xpath("//ol//li//ul") expect(page).not_to have_xpath("//ol//li//ul")
end end
end end
context 'with cached Redcarpet html' do
let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, cached_markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION) }
it 'renders correctly' do
expect(page).to have_xpath("//ol//li//ul")
end
end
end
context 'switching to the simple viewer' do context 'switching to the simple viewer' do
before do before do
find('.js-blob-viewer-switch-btn[data-viewer=simple]').click find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
......
...@@ -25,17 +25,17 @@ describe MarkupHelper do ...@@ -25,17 +25,17 @@ describe MarkupHelper do
let(:actual) { "#{merge_request.to_reference} -> #{commit.to_reference} -> #{issue.to_reference}" } let(:actual) { "#{merge_request.to_reference} -> #{commit.to_reference} -> #{issue.to_reference}" }
it "links to the merge request" do it "links to the merge request" do
expected = project_merge_request_path(project, merge_request) expected = urls.project_merge_request_path(project, merge_request)
expect(helper.markdown(actual)).to match(expected) expect(helper.markdown(actual)).to match(expected)
end end
it "links to the commit" do it "links to the commit" do
expected = project_commit_path(project, commit) expected = urls.project_commit_path(project, commit)
expect(helper.markdown(actual)).to match(expected) expect(helper.markdown(actual)).to match(expected)
end end
it "links to the issue" do it "links to the issue" do
expected = project_issue_path(project, issue) expected = urls.project_issue_path(project, issue)
expect(helper.markdown(actual)).to match(expected) expect(helper.markdown(actual)).to match(expected)
end end
end end
...@@ -46,7 +46,7 @@ describe MarkupHelper do ...@@ -46,7 +46,7 @@ describe MarkupHelper do
let(:second_issue) { create(:issue, project: second_project) } let(:second_issue) { create(:issue, project: second_project) }
it 'links to the issue' do it 'links to the issue' do
expected = project_issue_path(second_project, second_issue) expected = urls.project_issue_path(second_project, second_issue)
expect(markdown(actual, project: second_project)).to match(expected) expect(markdown(actual, project: second_project)).to match(expected)
end end
end end
...@@ -93,7 +93,7 @@ describe MarkupHelper do ...@@ -93,7 +93,7 @@ describe MarkupHelper do
# First issue link # First issue link
expect(doc.css('a')[1].attr('href')) expect(doc.css('a')[1].attr('href'))
.to eq project_issue_path(project, issues[0]) .to eq urls.project_issue_path(project, issues[0])
expect(doc.css('a')[1].text).to eq issues[0].to_reference expect(doc.css('a')[1].text).to eq issues[0].to_reference
# Internal commit link # Internal commit link
...@@ -102,7 +102,7 @@ describe MarkupHelper do ...@@ -102,7 +102,7 @@ describe MarkupHelper do
# Second issue link # Second issue link
expect(doc.css('a')[3].attr('href')) expect(doc.css('a')[3].attr('href'))
.to eq project_issue_path(project, issues[1]) .to eq urls.project_issue_path(project, issues[1])
expect(doc.css('a')[3].text).to eq issues[1].to_reference expect(doc.css('a')[3].text).to eq issues[1].to_reference
# Trailing commit link # Trailing commit link
...@@ -128,7 +128,7 @@ describe MarkupHelper do ...@@ -128,7 +128,7 @@ describe MarkupHelper do
# First issue link # First issue link
expect(doc.css('a')[1].attr('href')) expect(doc.css('a')[1].attr('href'))
.to eq project_issue_path(project, issues[0]) .to eq urls.project_issue_path(project, issues[0])
expect(doc.css('a')[1].text).to eq issues[0].to_reference expect(doc.css('a')[1].text).to eq issues[0].to_reference
# Internal commit link # Internal commit link
...@@ -137,7 +137,7 @@ describe MarkupHelper do ...@@ -137,7 +137,7 @@ describe MarkupHelper do
# Second issue link # Second issue link
expect(doc.css('a')[3].attr('href')) expect(doc.css('a')[3].attr('href'))
.to eq project_issue_path(project, issues[1]) .to eq urls.project_issue_path(project, issues[1])
expect(doc.css('a')[3].text).to eq issues[1].to_reference expect(doc.css('a')[3].text).to eq issues[1].to_reference
# Trailing commit link # Trailing commit link
...@@ -183,7 +183,7 @@ describe MarkupHelper do ...@@ -183,7 +183,7 @@ describe MarkupHelper do
doc = Nokogiri::HTML.parse(rendered) doc = Nokogiri::HTML.parse(rendered)
expect(doc.css('a')[0].attr('href')) expect(doc.css('a')[0].attr('href'))
.to eq project_issue_path(project, issue) .to eq urls.project_issue_path(project, issue)
expect(doc.css('a')[0].text).to eq issue.to_reference expect(doc.css('a')[0].text).to eq issue.to_reference
wrapped = helper.link_to_html(rendered, link) wrapped = helper.link_to_html(rendered, link)
...@@ -205,6 +205,17 @@ describe MarkupHelper do ...@@ -205,6 +205,17 @@ describe MarkupHelper do
it "uses Wiki pipeline for markdown files" do it "uses Wiki pipeline for markdown files" do
allow(@wiki).to receive(:format).and_return(:markdown) allow(@wiki).to receive(:format).and_return(:markdown)
expect(helper).to receive(:markdown_unsafe).with('wiki content',
pipeline: :wiki, project: project, project_wiki: @wiki, page_slug: "nested/page",
issuable_state_filter_enabled: true)
helper.render_wiki_content(@wiki)
end
it 'uses Wiki pipeline for markdown files with RedCarpet if feature disabled' do
stub_feature_flags(commonmark_for_repositories: false)
allow(@wiki).to receive(:format).and_return(:markdown)
expect(helper).to receive(:markdown_unsafe).with('wiki content', expect(helper).to receive(:markdown_unsafe).with('wiki content',
pipeline: :wiki, project: project, project_wiki: @wiki, page_slug: "nested/page", pipeline: :wiki, project: project, project_wiki: @wiki, page_slug: "nested/page",
issuable_state_filter_enabled: true, markdown_engine: :redcarpet) issuable_state_filter_enabled: true, markdown_engine: :redcarpet)
...@@ -259,10 +270,18 @@ describe MarkupHelper do ...@@ -259,10 +270,18 @@ describe MarkupHelper do
expect(helper.markup('foo.md', content, rendered: '<p>NOEL</p>')).to eq('<p>NOEL</p>') expect(helper.markup('foo.md', content, rendered: '<p>NOEL</p>')).to eq('<p>NOEL</p>')
end end
it 'defaults to Redcarpet' do it 'defaults to CommonMark' do
expect(helper).to receive(:markdown_unsafe).with(content, hash_including(markdown_engine: :redcarpet)).and_return('NOEL') expect(helper.markup('foo.md', 'x^2')).to include('x^2')
end
expect(helper.markup('foo.md', content)).to eq('NOEL') it 'honors markdown_engine for RedCarpet' do
expect(helper.markup('foo.md', 'x^2', { markdown_engine: :redcarpet })).to include('x<sup>2</sup>')
end
it 'uses RedCarpet if feature disabled' do
stub_feature_flags(commonmark_for_repositories: false)
expect(helper.markup('foo.md', 'x^2', { markdown_engine: :redcarpet })).to include('x<sup>2</sup>')
end end
end end
...@@ -414,4 +433,8 @@ describe MarkupHelper do ...@@ -414,4 +433,8 @@ describe MarkupHelper do
expect(helper.cross_project_reference(project, issue)).to include(project.full_path) expect(helper.cross_project_reference(project, issue)).to include(project.full_path)
end end
end end
def urls
Gitlab::Routing.url_helpers
end
end end
...@@ -479,4 +479,16 @@ describe ProjectsHelper do ...@@ -479,4 +479,16 @@ describe ProjectsHelper do
end end
end end
end end
describe '#legacy_render_context' do
it 'returns the redcarpet engine' do
params = { legacy_render: '1' }
expect(helper.legacy_render_context(params)).to include(markdown_engine: :redcarpet)
end
it 'returns nothing' do
expect(helper.legacy_render_context({})).to be_empty
end
end
end end
...@@ -121,6 +121,13 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -121,6 +121,13 @@ describe Banzai::Pipeline::WikiPipeline do
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"")
end end
it 'rewrites non-file links (with spaces) to be at the scope of the wiki root' do
markdown = "[Link to Page](page slug)"
output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page%20slug\"")
end
it "rewrites file links to be at the scope of the current directory" do it "rewrites file links to be at the scope of the current directory" do
markdown = "[Link to Page](page.md)" markdown = "[Link to Page](page.md)"
output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
...@@ -134,6 +141,13 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -134,6 +141,13 @@ describe Banzai::Pipeline::WikiPipeline do
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start-page#title\"") expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start-page#title\"")
end end
it 'rewrites links (with spaces) with anchor' do
markdown = '[Link to Header](start page#title)'
output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start%20page#title\"")
end
end end
describe "when creating root links" do describe "when creating root links" do
......
...@@ -119,6 +119,10 @@ describe Feature do ...@@ -119,6 +119,10 @@ describe Feature do
expect(described_class.enabled?(:some_random_feature_flag)).to be_falsey expect(described_class.enabled?(:some_random_feature_flag)).to be_falsey
end end
it 'returns true for undefined feature with default_enabled' do
expect(described_class.enabled?(:some_random_feature_flag, default_enabled: true)).to be_truthy
end
it 'returns false for existing disabled feature in the database' do it 'returns false for existing disabled feature in the database' do
described_class.disable(:disabled_feature_flag) described_class.disable(:disabled_feature_flag)
...@@ -160,6 +164,10 @@ describe Feature do ...@@ -160,6 +164,10 @@ describe Feature do
expect(described_class.disabled?(:some_random_feature_flag)).to be_truthy expect(described_class.disabled?(:some_random_feature_flag)).to be_truthy
end end
it 'returns false for undefined feature with default_enabled' do
expect(described_class.disabled?(:some_random_feature_flag, default_enabled: true)).to be_falsey
end
it 'returns true for existing disabled feature in the database' do it 'returns true for existing disabled feature in the database' do
described_class.disable(:disabled_feature_flag) described_class.disable(:disabled_feature_flag)
......
...@@ -328,6 +328,22 @@ describe RuboCop::Cop::LineBreakAroundConditionalBlock do ...@@ -328,6 +328,22 @@ describe RuboCop::Cop::LineBreakAroundConditionalBlock do
expect(cop.offenses).to be_empty expect(cop.offenses).to be_empty
end end
it "doesn't flag violation for #{conditional} preceded by a rescue" do
source = <<~RUBY
def a_method
do_something
rescue
#{conditional} condition
do_something
end
end
RUBY
inspect_source(source)
expect(cop.offenses).to be_empty
end
it "doesn't flag violation for #{conditional} followed by a rescue" do it "doesn't flag violation for #{conditional} followed by a rescue" do
source = <<~RUBY source = <<~RUBY
def a_method def a_method
......
...@@ -101,4 +101,11 @@ describe PreviewMarkdownService do ...@@ -101,4 +101,11 @@ describe PreviewMarkdownService do
expect(result[:markdown_engine]).to eq :common_mark expect(result[:markdown_engine]).to eq :common_mark
end end
it 'honors the legacy_render parameter' do
service = described_class.new(project, user, { legacy_render: '1' })
result = service.execute
expect(result[:markdown_engine]).to eq :redcarpet
end
end end
...@@ -4,8 +4,8 @@ module StubFeatureFlags ...@@ -4,8 +4,8 @@ module StubFeatureFlags
# @param [Hash] features where key is feature name and value is boolean whether enabled or not # @param [Hash] features where key is feature name and value is boolean whether enabled or not
def stub_feature_flags(features) def stub_feature_flags(features)
features.each do |feature_name, enabled| features.each do |feature_name, enabled|
allow(Feature).to receive(:enabled?).with(feature_name) { enabled } allow(Feature).to receive(:enabled?).with(feature_name, any_args) { enabled }
allow(Feature).to receive(:enabled?).with(feature_name.to_s) { enabled } allow(Feature).to receive(:enabled?).with(feature_name.to_s, any_args) { enabled }
end end
end end
end end
...@@ -5274,13 +5274,13 @@ moment@2.x, moment@^2.18.1: ...@@ -5274,13 +5274,13 @@ moment@2.x, moment@^2.18.1:
version "2.19.2" version "2.19.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe" resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe"
monaco-editor-webpack-plugin@^1.4.0: monaco-editor-webpack-plugin@^1.5.2:
version "1.4.0" version "1.5.2"
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.4.0.tgz#7324258ab3695464cfe3bc12edb2e8c55b80d92f" resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.5.2.tgz#e113fa1d5759ede6fd776eb620cdd5930203b55a"
monaco-editor@0.13.1: monaco-editor@^0.14.3:
version "0.13.1" version "0.14.3"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.13.1.tgz#6b9ce20e4d1c945042d256825eb133cb23315a52" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.14.3.tgz#7cc4a4096a3821f52fea9b10489b527ef3034e22"
mousetrap@^1.4.6: mousetrap@^1.4.6:
version "1.4.6" version "1.4.6"
......
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