summaryrefslogtreecommitdiffstats
path: root/test/unit/search_test.rb
blob: bd9477025940555704731ff39acf9ec8c30a74ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold }
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2015  Jean-Philippe Lang
#
# 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.

require File.expand_path('../../test_helper', __FILE__)

class SearchTest < ActiveSupport::TestCase
  fixtures :users,
           :members,
           :member_roles,
           :projects,
           :projects_trackers,
           :roles,
           :enabled_modules,
           :issues,
           :trackers,
           :issue_statuses,
           :enumerations,
           :journals,
           :journal_details,
           :repositories,
           :changesets

  def setup
    @project = Project.find(1)
    @issue_keyword = '%unable to print recipes%'
    @issue = Issue.find(1)
    @changeset_keyword = '%very first commit%'
    @changeset = Changeset.find(100)
  end

  def test_search_by_anonymous
    User.current = nil

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert r.include?(@changeset)

    # Removes the :view_changesets permission from Anonymous role
    remove_permission Role.anonymous, :view_changesets
    User.current = nil

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)

    # Make the project private
    @project.update_attribute :is_public, false
    r = Issue.search_results(@issue_keyword)
    assert !r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)
  end

  def test_search_by_user
    User.current = User.find_by_login('rhill')
    assert User.current.memberships.empty?

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert r.include?(@changeset)

    # Removes the :view_changesets permission from Non member role
    remove_permission Role.non_member, :view_changesets
    User.current = User.find_by_login('rhill')

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)

    # Make the project private
    @project.update_attribute :is_public, false
    r = Issue.search_results(@issue_keyword)
    assert !r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)
  end

  def test_search_by_allowed_member
    User.current = User.find_by_login('jsmith')
    assert User.current.projects.include?(@project)

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert r.include?(@changeset)

    # Make the project private
    @project.update_attribute :is_public, false
    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert r.include?(@changeset)
  end

  def test_search_by_unallowed_member
    # Removes the :view_changesets permission from user's and non member role
    remove_permission Role.find(1), :view_changesets
    remove_permission Role.non_member, :view_changesets

    User.current = User.find_by_login('jsmith')
    assert User.current.projects.include?(@project)

    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)

    # Make the project private
    @project.update_attribute :is_public, false
    r = Issue.search_results(@issue_keyword)
    assert r.include?(@issue)
    r = Changeset.search_results(@changeset_keyword)
    assert !r.include?(@changeset)
  end

  def test_search_issue_with_multiple_hits_in_journals
    issue = Issue.find(1)
    assert_equal 2, issue.journals.where("notes LIKE '%notes%'").count

    r = Issue.search_results('%notes%')
    assert_equal 1, r.size
    assert_equal issue, r.first
  end

  def test_search_should_be_case_insensitive
    issue = Issue.generate!(:subject => "AzerTY")

    r = Issue.search_results('AZERty')
    assert_include issue, r
  end

  def test_search_should_be_case_insensitive_with_accented_characters
    unless sqlite?
      issue1 = Issue.generate!(:subject => "Special chars: ÖÖ")
      issue2 = Issue.generate!(:subject => "Special chars: Öö")
  
      r = Issue.search_results('ÖÖ')
      assert_include issue1, r
      assert_include issue2, r
    end
  end

  def test_search_should_be_case_and_accent_insensitive_with_mysql
    if mysql?
      issue1 = Issue.generate!(:subject => "OO")
      issue2 = Issue.generate!(:subject => "oo")
  
      r = Issue.search_results('ÖÖ')
      assert_include issue1, r
      assert_include issue2, r
    end
  end

  def test_search_should_be_case_and_accent_insensitive_with_postgresql_and_noaccent_extension
    if postgresql?
      skip unless Redmine::Database.postgresql_version >= 90000
      # Extension will be rollbacked with the test transaction
      ActiveRecord::Base.connection.execute("CREATE EXTENSION IF NOT EXISTS unaccent")
      Redmine::Database.reset
      assert Redmine::Database.postgresql_unaccent?

      issue1 = Issue.generate!(:subject => "OO")
      issue2 = Issue.generate!(:subject => "oo")
  
      r = Issue.search_results('ÖÖ')
      assert_include issue1, r
      assert_include issue2, r
    end
  ensure
    Redmine::Database.reset
  end

  private

  def remove_permission(role, permission)
    role.permissions = role.permissions - [ permission ]
    role.save
  end
end