#-- encoding: UTF-8 #-- copyright # OpenProject is a project management system. # Copyright (C) 2012-2017 the OpenProject Foundation (OPF) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License version 3. # # OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: # Copyright (C) 2006-2017 Jean-Philippe Lang # Copyright (C) 2010-2013 the ChiliProject Team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # See doc/COPYRIGHT.rdoc for more details. #++ require 'legacy_spec_helper' describe ApplicationHelper, type: :helper do include OpenProject::StaticRouting include WorkPackagesHelper before do # @project variable is used by helper @project = FactoryGirl.create :valid_project @project.reload # reload references to indirectly created entities (e.g. wiki) @admin = FactoryGirl.create :admin @anonymous = FactoryGirl.create :anonymous @non_member = FactoryGirl.create :user @project_member = FactoryGirl.create :user, member_in_project: @project, member_through_role: FactoryGirl.create(:role, permissions: [:view_work_packages, :edit_work_packages, :browse_repository, :view_changesets, :view_wiki_pages]) @issue = FactoryGirl.create :work_package, project: @project, author: @project_member, type: @project.types.first file = LegacyFileHelpers.mock_uploaded_file name: 'logo.gif', content_type: 'image/gif', content: 'not actually a gif', binary: true @attachment = FactoryGirl.create :attachment, author: @project_member, file: file, content_type: 'image/gif', container: @issue, description: 'This is a logo' allow(User).to receive(:current).and_return(@project_member) end it 'should auto links' do to_test = { 'http://foo.bar' => 'http://foo.bar', 'http://foo.bar/~user' => 'http://foo.bar/~user', 'http://foo.bar.' => 'http://foo.bar.', 'https://foo.bar.' => 'https://foo.bar.', 'This is a link: http://foo.bar.' => 'This is a link: http://foo.bar.', 'A link (eg. http://foo.bar).' => 'A link (eg. http://foo.bar).', 'http://foo.bar/foo.bar#foo.bar.' => 'http://foo.bar/foo.bar#foo.bar.', 'http://www.foo.bar/Test_(foobar)' => 'http://www.foo.bar/Test_(foobar)', '(see inline link : http://www.foo.bar/Test_(foobar))' => '(see inline link : http://www.foo.bar/Test_(foobar))', '(see inline link : http://www.foo.bar/Test)' => '(see inline link : http://www.foo.bar/Test)', '(see inline link : http://www.foo.bar/Test).' => '(see inline link : http://www.foo.bar/Test).', '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see inline link)', '(see "inline link":http://www.foo.bar/Test)' => '(see inline link)', '(see "inline link":http://www.foo.bar/Test).' => '(see inline link).', 'www.foo.bar' => 'www.foo.bar', 'http://foo.bar/page?p=1&t=z&s=' => 'http://foo.bar/page?p=1&t=z&s=', 'http://foo.bar/page#125' => 'http://foo.bar/page#125', 'http://foo@www.bar.com' => 'http://foo@www.bar.com', 'http://foo:bar@www.bar.com' => 'http://foo:bar@www.bar.com', 'ftp://foo.bar' => 'ftp://foo.bar', 'ftps://foo.bar' => 'ftps://foo.bar', 'sftp://foo.bar' => 'sftp://foo.bar', # two exclamation marks 'http://example.net/path!602815048C7B5C20!302.html' => 'http://example.net/path!602815048C7B5C20!302.html', # escaping 'http://foo"bar' => 'http://foo"bar', # wrap in angle brackets '' => '<http://foo.bar>' } to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text) } end it 'should auto mailto' do assert_dom_equal '

', helper.format_text('test@foo.bar') end it 'should inline images' do to_test = { '!http://foo.bar/image.jpg!' => '', 'floating !>http://foo.bar/image.jpg!' => 'floating
', 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class ', # inline styles should be stripped 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style ', 'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title This is a title', 'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title This is a double-quoted "title"', } to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text) } end it 'should inline images inside tags' do raw = <<-RAW h1. !foo.png! Heading Centered image: p=. !bar.gif! RAW assert helper.format_text(raw).include?('') assert helper.format_text(raw).include?('') end it 'should attached images' do to_test = { 'Inline image: !logo.gif!' => "Inline image: \"This", 'Inline image: !logo.GIF!' => "Inline image: \"This", 'No match: !ogo.gif!' => 'No match: ', 'No match: !ogo.GIF!' => 'No match: ', # link image '!logo.gif!:http://foo.bar/' => "\"This", } to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text, attachments: [@attachment]) } end it 'should textile external links' do to_test = { 'This is a "link":http://foo.bar' => 'This is a link', 'This is an intern "link":/foo/bar' => 'This is an intern link', '"link (Link title)":http://foo.bar' => 'link', '"link (Link title with "double-quotes")":http://foo.bar' => 'link', "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":

\n\n\n\t

Another paragraph", # no multiline link text "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line
and another on a second line\":test", # mailto link "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "system administrator", # two exclamation marks '"a link":http://example.net/path!602815048C7B5C20!302.html' => 'a link', # escaping '"test":http://foo"bar' => 'test', } to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text) } end it 'should textile relative to full links in a controller', :with_mock_request_for_helper do { # shouldn't change non-relative links 'This is a "link":http://foo.bar' => 'This is a link', 'This is an intern "link":/foo/bar' => 'This is an intern link', 'This is an intern "link":/foo/bar and an extern "link":http://foo.bar' => 'This is an intern link and an extern link', }.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text, only_path: false) } end it 'should textile relative to full links in the mailer' do # mimic the mailer default_url_options @controller.class.class_eval do def self.default_url_options ::UserMailer.default_url_options end end { # shouldn't change non-relative links 'This is a "link":http://foo.bar' => 'This is a link', 'This is an intern "link":/foo/bar' => 'This is an intern link', 'This is an intern "link":/foo/bar and an extern "link":http://foo.bar' => 'This is an intern link and an extern link', }.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text, only_path: false) } end it 'should cross project redmine links' do version = FactoryGirl.create :version, name: '1.0', project: @project to_test = { # versions 'version:"1.0"' => 'version:"1.0"', "#{@project.identifier}:version:\"1.0\"" => "1.0", 'invalid:version:"1.0"' => 'invalid:version:"1.0"' } repository = FactoryGirl.create :repository_subversion, project: @project changeset = FactoryGirl.create :changeset, repository: repository, comments: 'This commit fixes #1, #2 and references #1 & #3' identifier = @project.identifier source_link = link_to("#{identifier}:source:/some/file", { controller: 'repositories', action: 'entry', project_id: identifier, path: 'some/file' }, class: 'source') changeset_link = link_to("#{identifier}:r#{changeset.revision}", { controller: 'repositories', action: 'revision', project_id: identifier, rev: changeset.revision }, class: 'changeset', title: 'This commit fixes #1, #2 and references #1 & #3') to_test.merge!( # changeset "r#{changeset.revision}" => "r#{changeset.revision}", "#{@project.identifier}:r#{changeset.revision}" => changeset_link, "invalid:r#{changeset.revision}" => "invalid:r#{changeset.revision}", # source 'source:/some/file' => 'source:/some/file', "#{@project.identifier}:source:/some/file" => source_link, 'invalid:source:/some/file' => 'invalid:source:/some/file', ) # helper.format_text "sees" the text is parses from the_other_project (and not @project) the_other_project = FactoryGirl.create :valid_project to_test.each do |text, result| assert_dom_equal "

#{result}

", helper.format_text(text, project: the_other_project), "#{text} failed" end end it 'should redmine links git commit' do allow(User).to receive(:current).and_return(@admin) changeset_link = link_to('abcd', { controller: 'repositories', action: 'revision', project_id: @project.identifier, rev: 'abcd', }, class: 'changeset', title: 'test commit') to_test = { 'commit:abcd' => changeset_link, } r = Repository::Git.create!(project: @project, scm_type: 'local', url: '/tmp/test/git') assert r c = Changeset.new(repository: r, committed_on: Time.now, revision: 'abcd', scmid: 'abcd', comments: 'test commit') assert(c.save) @project.reload to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text) } end it 'should attachment links' do attachment_link = link_to('logo.gif', { controller: 'attachments', action: 'download', id: @attachment }, class: 'attachment') to_test = { 'attachment:logo.gif' => attachment_link } to_test.each { |text, result| assert_dom_equal "

#{result}

", helper.format_text(text, attachments: [@attachment]), "#{text} failed" } end it 'should html tags' do to_test = { '
content
' => '

<div>content</div>

', "
content
" => "

<div class=\"bold\">content</div>

", '' => '

<script>some script;</script>

', # do not escape pre/code tags "
\nline 1\nline2
" => "
\nline 1\nline2
", "
\nline 1\nline2
" => "
\nline 1\nline2
", '
content
' => '
<div>content</div>
', 'HTML comment: ' => '

HTML comment: <!-- no comments -->

', '