fix ticketing system error on bootstrap of new install
[freeside.git] / rt / t / web / simple_search.t
1 use strict;
2 use warnings;
3
4 use RT::Test tests => undef,
5     config => 'Set( %FullTextSearch, Enable => 1, Indexed => 0 );';
6 my ($baseurl, $m) = RT::Test->started_ok;
7 my $url = $m->rt_base_url;
8
9 my $queue = RT::Queue->new($RT::SystemUser);
10 $queue->Create( Name => 'other' );
11 ok( $queue->id, 'created queue other');
12
13 my $two_words_queue = RT::Test->load_or_create_queue(
14     Name => 'Two Words',
15 );
16 ok $two_words_queue && $two_words_queue->id, 'loaded or created a queue';
17
18
19 {
20     my $tickets = RT::Tickets->new( RT->SystemUser );
21     my $active = "( ".join( " OR ", map "Status = '$_'", RT::Queue->ActiveStatusArray())." )";
22     my $inactive = "( ".join( " OR ", map "Status = '$_'", RT::Queue->InactiveStatusArray())." )";
23
24     require RT::Search::Simple;
25     my $parser = RT::Search::Simple->new(
26         TicketsObj => $tickets,
27         Argument   => '',
28     );
29     is $parser->QueryToSQL("foo"), "( Subject LIKE 'foo' ) AND $active", "correct parsing";
30     is $parser->QueryToSQL("1 foo"), "( Subject LIKE 'foo' AND Subject LIKE '1' ) AND $active", "correct parsing";
31     is $parser->QueryToSQL("1"), "( Id = 1 )", "correct parsing";
32     is $parser->QueryToSQL("#1"), "( Id = 1 )", "correct parsing";
33     is $parser->QueryToSQL("'1'"), "( Subject LIKE '1' ) AND $active", "correct parsing";
34
35     is $parser->QueryToSQL("foo bar"),
36         "( Subject LIKE 'foo' AND Subject LIKE 'bar' ) AND $active",
37         "correct parsing";
38     is $parser->QueryToSQL("'foo bar'"),
39         "( Subject LIKE 'foo bar' ) AND $active",
40         "correct parsing";
41
42     is $parser->QueryToSQL("'foo \\' bar'"),
43         "( Subject LIKE 'foo \\' bar' ) AND $active",
44         "correct parsing";
45     is $parser->QueryToSQL('"foo \' bar"'),
46         "( Subject LIKE 'foo \\' bar' ) AND $active",
47         "correct parsing";
48     is $parser->QueryToSQL('"\f\o\o"'),
49         "( Subject LIKE '\\\\f\\\\o\\\\o' ) AND $active",
50         "correct parsing";
51
52     is $parser->QueryToSQL("General"), "( Queue = 'General' ) AND $active", "correct parsing";
53     is $parser->QueryToSQL("'Two Words'"), "( Subject LIKE 'Two Words' ) AND $active", "correct parsing";
54     is $parser->QueryToSQL("queue:'Two Words'"), "( Queue = 'Two Words' ) AND $active", "correct parsing";
55     is $parser->QueryToSQL("subject:'Two Words'"), "$active AND ( Subject LIKE 'Two Words' )", "correct parsing";
56
57     is $parser->QueryToSQL("me"), "( Owner.id = '__CurrentUser__' ) AND $active", "correct parsing";
58     is $parser->QueryToSQL("'me'"), "( Subject LIKE 'me' ) AND $active", "correct parsing";
59     is $parser->QueryToSQL("owner:me"), "( Owner.id = '__CurrentUser__' ) AND $active", "correct parsing";
60     is $parser->QueryToSQL("owner:'me'"), "( Owner = 'me' ) AND $active", "correct parsing";
61     is $parser->QueryToSQL('owner:root@localhost'), "( Owner.EmailAddress = 'root\@localhost' ) AND $active", "Email address as owner";
62
63     is $parser->QueryToSQL("resolved me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' )", "correct parsing";
64     is $parser->QueryToSQL("resolved active me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' OR Status = 'new' OR Status = 'open' OR Status = 'stalled' )", "correct parsing";
65     is $parser->QueryToSQL("status:active"), $active, "Explicit active search";
66     is $parser->QueryToSQL("status:'active'"), "( Status = 'active' )", "Quoting active makes it the actual word";
67     is $parser->QueryToSQL("inactive me"), "( Owner.id = '__CurrentUser__' ) AND $inactive", "correct parsing";
68
69     is $parser->QueryToSQL("cf.Foo:bar"), "( 'CF.{Foo}' LIKE 'bar' ) AND $active", "correct parsing of CFs";
70     is $parser->QueryToSQL(q{cf."don't foo?":'bar n\\' baz'}), qq/( 'CF.{don\\'t foo?}' LIKE 'bar n\\' baz' ) AND $active/, "correct parsing of CFs with quotes";
71 }
72
73 my $ticket_found_1 = RT::Ticket->new($RT::SystemUser);
74 my $ticket_found_2 = RT::Ticket->new($RT::SystemUser);
75 my $ticket_not_found = RT::Ticket->new($RT::SystemUser);
76
77 $ticket_found_1->Create(
78     Subject   => 'base ticket 1'.$$,
79     Queue     => 'general',
80     Owner     => 'root',
81     Requestor => 'customsearch@localhost',
82     Content   => 'this is base ticket 1',
83 );
84 ok( $ticket_found_1->id, 'created ticket for custom search');
85
86
87 $ticket_found_2->Create(
88     Subject   => 'base ticket 2'.$$,
89     Queue     => 'general',
90     Owner     => 'root',
91     Requestor => 'customsearch@localhost',
92     Content   => 'this is base ticket 2',
93 );
94 ok( $ticket_found_2->id, 'created ticket for custom search');
95
96 $ticket_not_found = RT::Ticket->new($RT::SystemUser);
97 $ticket_not_found->Create(
98     Subject   => 'not found subject' . $$,
99     Queue     => 'other',
100     Owner     => 'nobody',
101     Requestor => 'notfound@localhost',
102     Content   => 'this is not found content',
103 );
104 ok( $ticket_not_found->id, 'created ticket for custom search');
105
106 ok($m->login, 'logged in');
107
108 my @queries = (
109     'base ticket',            'root',
110     'customsearch@localhost', 'requestor:customsearch',
111     'subject:base',           'subject:"base ticket"',
112     'queue:general',          'owner:root',
113 );
114
115 for my $q (@queries) {
116     $m->form_with_fields('q');
117     $m->field( q => $q );
118     $m->submit;
119     $m->content_contains( 'base ticket 1', 'base ticket 1 is found' );
120     $m->content_contains( 'base ticket 2', 'base ticket 2 is found' );
121     $m->content_lacks( 'not found subject', 'not found ticket is not found' );
122 }
123
124 $ticket_not_found->SetStatus('open');
125 is( $ticket_not_found->Status, 'open', 'status of not found ticket is open' );
126 @queries = qw/new status:new/;
127 for my $q (@queries) {
128     $m->form_with_fields('q');
129     $m->field( q => $q );
130     $m->submit;
131     $m->content_contains( 'base ticket 1', 'base ticket 1 is found' );
132     $m->content_contains( 'base ticket 2', 'base ticket 2 is found' );
133     $m->content_lacks( 'not found subject', 'not found ticket is not found' );
134 }
135
136 @queries = ( 'fulltext:"base ticket 1"', "'base ticket 1'" );
137 for my $q (@queries) {
138     $m->form_with_fields('q');
139     $m->field( q => $q );
140     $m->submit;
141     $m->content_contains( 'base ticket 1', 'base ticket 1 is found' );
142     $m->content_lacks( 'base ticket 2',     'base ticket 2 is not found' );
143     $m->content_lacks( 'not found subject', 'not found ticket is not found' );
144 }
145
146 # now let's test with ' or "
147 for my $quote ( q{'}, q{"} ) {
148     my $user = RT::User->new($RT::SystemUser);
149     is( ref($user), 'RT::User' );
150     my ( $id, $msg ) = $user->Create(
151         Name         => qq!foo${quote}bar!,
152         EmailAddress => qq!foo${quote}bar$$\@example.com !,
153         Privileged   => 1,
154     );
155     ok ($id, "Creating user - " . $msg );
156
157     my ( $grantid, $grantmsg ) =
158       $user->PrincipalObj->GrantRight( Right => 'OwnTicket' );
159     ok( $grantid, $grantmsg );
160
161
162
163     my $ticket_quote = RT::Ticket->new($RT::SystemUser);
164     $ticket_quote->Create(
165         Subject   => qq!base${quote}ticket $$!,
166         Queue     => 'general',
167         Owner     => $user->Name,
168         ( $quote eq q{'}
169             ? (Requestor => qq!custom${quote}search\@localhost!)
170             : () ),
171         Content   => qq!this is base${quote}ticket with quote inside!,
172     );
173     ok( $ticket_quote->id, 'created ticket with quote for custom search' );
174
175     @queries = (
176         qq!fulltext:base${quote}ticket!,
177         "base${quote}ticket",
178         "owner:foo${quote}bar",
179         "foo${quote}bar",
180
181         # email doesn't allow " character
182         $quote eq q{'}
183         ? (
184             "requestor:custom${quote}search\@localhost",
185             "custom${quote}search\@localhost",
186           )
187         : (),
188     );
189     for my $q (@queries) {
190         $m->form_with_fields('q');
191         $m->field( q => $q );
192         $m->submit;
193         my $escape_quote = $quote;
194         RT::Interface::Web::EscapeHTML(\$escape_quote);
195         $m->content_contains( "base${escape_quote}ticket",
196             "base${quote}ticket is found" );
197     }
198 }
199
200 # Create a CF
201 {
202     my $cf = RT::CustomField->new(RT->SystemUser);
203     ok( $cf->Create(Name => 'Foo', Type => 'Freeform', MaxValues => '1', Queue => 0) );
204     ok $cf->Id;
205
206     $ticket_found_1->AddCustomFieldValue( Field => 'Foo', Value => 'bar' );
207     $ticket_found_2->AddCustomFieldValue( Field => 'Foo', Value => 'bar' );
208     $ticket_not_found->AddCustomFieldValue( Field => 'Foo', Value => 'baz' );
209     is( $ticket_found_1->FirstCustomFieldValue('Foo'), 'bar', 'cf value is ok' );
210     is( $ticket_found_2->FirstCustomFieldValue('Foo'), 'bar', 'cf value is ok' );
211     is( $ticket_not_found->FirstCustomFieldValue('Foo'), 'baz', 'cf value is ok' );
212
213     @queries = qw/cf.Foo:bar/;
214     for my $q (@queries) {
215         $m->form_with_fields('q');
216         $m->field( q => $q );
217         $m->submit;
218         $m->content_contains( 'base ticket 1', 'base ticket 1 is found' );
219         $m->content_contains( 'base ticket 2', 'base ticket 2 is found' );
220         $m->content_lacks( 'not found subject', 'not found ticket is not found' );
221     }
222 }
223
224 undef $m;
225 done_testing;