diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 7923e34066..56ffe6378c 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -134,6 +134,7 @@ describe ApplicationHelper do describe ".textilizable" do let(:project) { FactoryGirl.create :valid_project } + let(:identifier) { project.identifier } let(:project_member) { FactoryGirl.create :user, :member_in_project => project, :member_through_role => FactoryGirl.create(:role, @@ -145,15 +146,267 @@ describe ApplicationHelper do :tracker => project.trackers.first } before do - project.reload - project.wiki.start_page = "CookBook documentation" - project.wiki.save! - FactoryGirl.create :wiki_page_with_content, :wiki => project.wiki, :title => "CookBook_documentation" + @project = project User.stubs(:current).returns(project_member) + + Setting.enabled_scm = Setting.enabled_scm << "Filesystem" unless Setting.enabled_scm.include? "Filesystem" + end + + after do + User.unstub(:current) + + Setting.enabled_scm.delete "Filesystem" + end + + context "Changeset links" do + let(:repository) { FactoryGirl.create :repository, :project => project } + let(:changeset1) { FactoryGirl.create :changeset, + :repository => repository, + :comments => 'My very first commit' } + let(:changeset2) { FactoryGirl.create :changeset, + :repository => repository, + :comments => 'This commit fixes #1, #2 and references #1 & #3' } + let(:changeset_link) { link_to("r#{changeset1.revision}", + {:controller => 'repositories', :action => 'revision', :id => identifier, :rev => changeset1.revision}, + :class => 'changeset', :title => 'My very first commit') } + let(:changeset_link2) { link_to("r#{changeset2.revision}", + {:controller => 'repositories', :action => 'revision', :id => identifier, :rev => changeset2.revision}, + :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') } + + before do + project.repository = repository + end + + context "Single link" do + subject { textilizable("r#{changeset1.revision}") } + + it { should eq("

#{changeset_link}

") } + end + + context "Single link with dot" do + subject { textilizable("r#{changeset1.revision}.") } + + it { should eq("

#{changeset_link}.

") } + end + + context "Two links comma separated" do + subject { textilizable("r#{changeset1.revision}, r#{changeset2.revision}") } + + it { should eq("

#{changeset_link}, #{changeset_link2}

") } + end + + context "Single link comma separated without a space" do + subject { textilizable("r#{changeset1.revision},r#{changeset2.revision}") } + + it { should eq("

#{changeset_link},#{changeset_link2}

") } + end + + context "Escaping" do + subject { textilizable("!r#{changeset1.id}") } + + it { should eq("

r#{changeset1.id}

") } + end + end + + context "Document links" do + let(:document) { FactoryGirl.create :document, + :title => 'Test document', + :project => project } + let(:document_link) { link_to('Test document', + {:controller => 'documents', :action => 'show', :id => document.id}, + :class => 'document') } + + context "Plain link" do + subject { textilizable("document##{document.id}") } + + it { should eq("

#{document_link}

") } + end + + context "Link with document name" do + subject { textilizable("document##{document.id}") } + + it { should eq("

#{document_link}

") } + end + + context "Escaping plain link" do + subject { textilizable("!document##{document.id}") } + + it { should eq("

document##{document.id}

") } + end + + context "Escaping link with document name" do + subject { textilizable('!document:"Test document"') } + + it { should eq('

document:"Test document"

') } + end + end + + context "Version link" do + let(:version) { FactoryGirl.create :version, + :name => '1.0', + :project => project } + let(:version_link) { link_to('1.0', + {:controller => 'versions', :action => 'show', :id => version.id}, + :class => 'version') } + + context "Link with version id" do + subject { textilizable("version##{version.id}") } + + it { should eq("

#{version_link}

") } + end + + context "Link with version" do + subject { textilizable("version:1.0") } + it { should eq("

#{version_link}

") } + end + + context "Link with quoted version" do + subject { textilizable('version:"1.0"') } + + it { should eq("

#{version_link}

") } + end + + context "Escaping link with version id" do + subject { textilizable("!version##{version.id}") } + + it { should eq("

version##{version.id}

") } + end + + context "Escaping link with version" do + subject { textilizable("!version:1.0") } + + it { should eq("

version:1.0

") } + end + + context "Escaping link with quoted version" do + subject { textilizable('!version:"1.0"') } + + it { should eq('

version:"1.0"

') } + end + end + + context "Message links" do + let(:board) { FactoryGirl.create :board, :project => project } + let(:message1) { FactoryGirl.create :message, :board => board } + let(:message2) { FactoryGirl.create :message, + :board => board, + :parent => message1 } + + before do + message1.reload + @message_url = {:controller => 'messages', :action => 'show', :board_id => board.id, :id => message1.id} + end + + context "Plain message" do + subject { textilizable("message##{message1.id}") } + + it { should eq("

#{link_to(message1.subject, @message_url, :class => 'message')}

") } + end + + context "Message with parent" do + subject { textilizable("message##{message2.id}") } + + it { should eq("

#{link_to(message2.subject, @message_url.merge(:anchor => "message-#{message2.id}", :r => message2.id), :class => 'message')}

") } + end + end + + context "Issue links" do + let(:issue_link) { link_to("##{issue.id}", + work_package_path(issue), + :class => 'issue work_package status-3 priority-1 created-by-me', :title => "#{issue.subject} (#{issue.status})") } + + context "Plain issue link" do + subject { textilizable("##{issue.id}, [##{issue.id}], (##{issue.id}) and ##{issue.id}.") } + + it { should eq("

#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.

") } + end + + context "Plain issue link to non-existing element" do + subject { textilizable('#0123456789') } + + it { should eq('

#0123456789

') } + end + + context "Escaping issue link" do + subject { textilizable("!##{issue.id}.") } + + it { should eq("

##{issue.id}.

") } + end + end + + context "Project links" do + let(:subproject) { FactoryGirl.create :valid_project, :parent => project } + let(:project_url) { {:controller => 'projects', :action => 'show', :id => subproject.identifier} } + + context "Plain project link" do + subject { textilizable("project##{subproject.id}") } + + it { should eq("

#{link_to(subproject.name, project_url, :class => 'project')}

") } + end + + context "Plain project link via identifier" do + subject { textilizable("project:#{subproject.identifier}") } + + it { should eq("

#{link_to(subproject.name, project_url, :class => 'project')}

") } + end + + context "Plain project link via name" do + subject { textilizable("project:\"#{subproject.name}\"") } + + it { should eq("

#{link_to(subproject.name, project_url, :class => 'project')}

") } + end + end + + context "Url links" do + subject { textilizable("http://foo.bar/FAQ#3") } + + it { should eq('

http://foo.bar/FAQ#3

') } + end + + context "Redmine links" do + let(:repository) { FactoryGirl.create :repository, :project => project } + let(:source_url) { {:controller => 'repositories', :action => 'entry', :id => identifier, :path => ['some', 'file']} } + let(:source_url_with_ext) { {:controller => 'repositories', :action => 'entry', :id => identifier, :path => ['some', 'file.ext']} } + + before do + project.repository = repository + + @to_test = { + # source + 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'), + 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".", + 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", + 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".", + 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", + 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",", + 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'), + 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'), + 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'), + 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'), + 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'), + 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'), + # escaping + '!source:/some/file' => 'source:/some/file', + # invalid expressions + 'source:' => 'source:', + } + end + + it "" do + @to_test.each do |text, result| + textilizable(text).should eql("

#{result}

") + end + end end context "Pre content should not parse wiki and redmine links" do + let(:wiki) { FactoryGirl.create :wiki, + :start_page => "CookBook documentation", + :project => project } + let(:wiki_page) { FactoryGirl.create :wiki_page_with_content, + :wiki => wiki, + :title => "CookBook_documentation" } let(:raw) { <<-RAW [[CookBook documentation]] @@ -165,7 +418,7 @@ describe ApplicationHelper do ##{issue.id} RAW - } + } let(:expected) { <<-EXPECTED

CookBook documentation

@@ -176,7 +429,13 @@ RAW ##{issue.id} EXPECTED - } + } + + before do + project.wiki = wiki + wiki.pages << wiki_page + end + subject { textilizable(raw).gsub(%r{[\r\n\t]}, '')} diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb index ba28dacc1c..8f02bcd97c 100644 --- a/test/unit/helpers/application_helper_test.rb +++ b/test/unit/helpers/application_helper_test.rb @@ -171,110 +171,6 @@ RAW }.each { |text, result| assert_equal "

#{result}

", textilizable(text, :only_path => false) } end - def test_redmine_links - document = FactoryGirl.create :document, - :title => 'Test document', - :project => @project - version = FactoryGirl.create :version, - :name => '1.0', - :project => @project - Setting.enabled_scm = Setting.enabled_scm << "Filesystem" unless Setting.enabled_scm.include? "Filesystem" - repository = FactoryGirl.create :repository, - :project => @project - changeset1 = FactoryGirl.create :changeset, - :repository => repository, - :comments => 'My very first commit' - changeset2 = FactoryGirl.create :changeset, - :repository => repository, - :comments => 'This commit fixes #1, #2 and references #1 & #3' - board = FactoryGirl.create :board, - :project => @project - message1 = FactoryGirl.create :message, - :board => board - message2 = FactoryGirl.create :message, - :board => board, - :parent => message1 - message1.reload - subproject = FactoryGirl.create :valid_project, - :parent => @project - identifier = @project.identifier - @project.reload - - issue_link = link_to("##{@issue.id}", work_package_path(@issue), - :class => 'issue work_package status-3 priority-1 created-by-me', :title => "#{@issue.subject} (#{@issue.status})") - - changeset_link = link_to("r#{changeset1.revision}", {:controller => 'repositories', :action => 'revision', :id => identifier, :rev => changeset1.revision}, - :class => 'changeset', :title => 'My very first commit') - changeset_link2 = link_to("r#{changeset2.revision}", {:controller => 'repositories', :action => 'revision', :id => identifier, :rev => changeset2.revision}, - :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') - - document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => document.id}, - :class => 'document') - - version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => version.id}, - :class => 'version') - - message_url = {:controller => 'messages', :action => 'show', :board_id => board.id, :id => message1.id} - - project_url = {:controller => 'projects', :action => 'show', :id => subproject.identifier} - - source_url = {:controller => 'repositories', :action => 'entry', :id => identifier, :path => ['some', 'file']} - source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => identifier, :path => ['some', 'file.ext']} - - to_test = { - # tickets - "##{@issue.id}, [##{@issue.id}], (##{@issue.id}) and ##{@issue.id}." => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.", - # changesets - "r#{changeset1.revision}" => changeset_link, - "r#{changeset1.revision}." => "#{changeset_link}.", - "r#{changeset1.revision}, r#{changeset2.revision}" => "#{changeset_link}, #{changeset_link2}", - "r#{changeset1.revision},r#{changeset2.revision}" => "#{changeset_link},#{changeset_link2}", - # documents - "document##{document.id}" => document_link, - 'document:"Test document"' => document_link, - # versions - "version##{version.id}" => version_link, - 'version:1.0' => version_link, - 'version:"1.0"' => version_link, - # source - 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'), - 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".", - 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", - 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".", - 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", - 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",", - 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'), - 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'), - 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'), - 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'), - 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'), - 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'), - # message - "message##{message1.id}" => link_to(message1.subject, message_url, :class => 'message'), - "message##{message2.id}" => link_to(message2.subject, message_url.merge(:anchor => "message-#{message2.id}", :r => message2.id), :class => 'message'), - # project - "project##{subproject.id}" => link_to(subproject.name, project_url, :class => 'project'), - "project:#{subproject.identifier}" => link_to(subproject.name, project_url, :class => 'project'), - "project:\"#{subproject.name}\"" => link_to(subproject.name, project_url, :class => 'project'), - # escaping - "!##{@issue.id}." => "##{@issue.id}.", - "!r#{changeset1.id}" => "r#{changeset1.id}", - "!document##{document.id}" => "document##{document.id}", - '!document:"Test document"' => 'document:"Test document"', - "!version##{version.id}" => "version##{version.id}", - '!version:1.0' => 'version:1.0', - '!version:"1.0"' => 'version:"1.0"', - '!source:/some/file' => 'source:/some/file', - # not found - '#0123456789' => '#0123456789', - # invalid expressions - 'source:' => 'source:', - # url hash - "http://foo.bar/FAQ#3" => 'http://foo.bar/FAQ#3', - } - to_test.each { |text, result| assert_equal "

#{result}

", textilizable(text), "#{text} failed" } - end - def test_cross_project_redmine_links document = FactoryGirl.create :document, :title => 'Test document',