RT 4.0.22
[freeside.git] / rt / t / web / query_builder.t
1 use strict;
2 use warnings;
3 use HTTP::Request::Common;
4 use HTTP::Cookies;
5 use LWP;
6 use RT::Test tests => 70;
7
8 my $cookie_jar = HTTP::Cookies->new;
9 my ($baseurl, $agent) = RT::Test->started_ok;
10
11
12 # give the agent a place to stash the cookies
13
14 $agent->cookie_jar($cookie_jar);
15
16 # create a regression queue if it doesn't exist
17 my $queue = RT::Test->load_or_create_queue( Name => 'Regression' );
18 ok $queue && $queue->id, 'loaded or created queue';
19
20 my $url = $agent->rt_base_url;
21 ok $agent->login, "logged in";
22
23
24 my $response = $agent->get($url."Search/Build.html");
25 ok $response->is_success, "Fetched ". $url ."Search/Build.html";
26
27 sub getQueryFromForm {
28     my $agent = shift;
29     $agent->form_name('BuildQuery');
30     # This pulls out the "hidden input" query from the page
31     my $q = $agent->current_form->find_input("Query")->value;
32     $q =~ s/^\s+//g;
33     $q =~ s/\s+$//g;
34     $q =~ s/\s+/ /g;
35     return $q;
36 }
37
38 sub selectedClauses {
39     my $agent = shift;
40     my @clauses = grep { defined } map { $_->value } $agent->current_form->find_input("clauses");
41     return [ @clauses ];
42 }
43
44
45 diag "add the first condition";
46 {
47     ok $agent->form_name('BuildQuery'), "found the form once";
48     $agent->field("ActorField", "Owner");
49     $agent->field("ActorOp", "=");
50     $agent->field("ValueOfActor", "Nobody");
51     $agent->submit;
52     is getQueryFromForm($agent), "Owner = 'Nobody'", 'correct query';
53 }
54
55 diag "set the next condition";
56 {
57     ok($agent->form_name('BuildQuery'), "found the form again");
58     $agent->field("QueueOp", "!=");
59     $agent->field("ValueOfQueue", "Regression");
60     $agent->submit;
61     is getQueryFromForm($agent), "Owner = 'Nobody' AND Queue != 'Regression'",
62         'correct query';
63 }
64
65 diag "We're going to delete the owner";
66 {
67     $agent->select("clauses", ["0"] );
68     $agent->click("DeleteClause");
69     ok $agent->form_name('BuildQuery'), "found the form";
70     is getQueryFromForm($agent), "Queue != 'Regression'", 'correct query';
71 }
72
73 diag "add a cond with OR and se number by the way";
74 {
75     $agent->field("AndOr", "OR");
76     $agent->select("idOp", ">");
77     $agent->field("ValueOfid" => "1234");
78     $agent->click("AddClause");
79     ok $agent->form_name('BuildQuery'), "found the form again";
80     is getQueryFromForm($agent), "Queue != 'Regression' OR id > 1234",
81         "added something as OR, and number not quoted";
82     is_deeply selectedClauses($agent), ["1"], 'the id that we just entered is still selected';
83
84 }
85
86 diag "Move the second one up a level";
87 {
88     $agent->click("Up");
89     ok $agent->form_name('BuildQuery'), "found the form again";
90     is getQueryFromForm($agent), "id > 1234 OR Queue != 'Regression'", "moved up one";
91     is_deeply selectedClauses($agent), ["0"], 'the one we moved up is selected';
92 }
93
94 diag "Move the second one right";
95 {
96     $agent->click("Right");
97     ok $agent->form_name('BuildQuery'), "found the form again";
98     is getQueryFromForm($agent), "Queue != 'Regression' OR ( id > 1234 )",
99         "moved over to the right (and down)";
100     is_deeply selectedClauses($agent), ["2"], 'the one we moved right is selected';
101 }
102
103 diag "Move the block up";
104 {
105     $agent->select("clauses", ["1"]);
106     $agent->click("Up");
107     ok $agent->form_name('BuildQuery'), "found the form again";
108     is getQueryFromForm($agent), "( id > 1234 ) OR Queue != 'Regression'", "moved up";
109     is_deeply selectedClauses($agent), ["0"], 'the one we moved up is selected';
110 }
111
112
113 diag "Can not move up the top most clause";
114 {
115     $agent->select("clauses", ["0"]);
116     $agent->click("Up");
117     ok $agent->form_name('BuildQuery'), "found the form again";
118     $agent->content_contains("error: can't move up", "i shouldn't have been able to hit up");
119     is_deeply selectedClauses($agent), ["0"], 'the one we tried to move is selected';
120 }
121
122 diag "Can not move left the left most clause";
123 {
124     $agent->click("Left");
125     ok($agent->form_name('BuildQuery'), "found the form again");
126     $agent->content_contains("error: can't move left", "i shouldn't have been able to hit left");
127     is_deeply selectedClauses($agent), ["0"], 'the one we tried to move is selected';
128 }
129
130 diag "Add a condition into a nested block";
131 {
132     $agent->select("clauses", ["1"]);
133     $agent->select("ValueOfStatus" => "stalled");
134     $agent->submit;
135     ok $agent->form_name('BuildQuery'), "found the form again";
136     is_deeply selectedClauses($agent), ["2"], 'the one we added is only selected';
137     is getQueryFromForm($agent),
138         "( id > 1234 AND Status = 'stalled' ) OR Queue != 'Regression'",
139         "added new one";
140 }
141
142 diag "click advanced, enter 'C1 OR ( C2 AND C3 )', apply, aggregators should stay the same.";
143 {
144     my $response = $agent->get($url."Search/Edit.html");
145     ok( $response->is_success, "Fetched /Search/Edit.html" );
146     ok($agent->form_name('BuildQueryAdvanced'), "found the form");
147     $agent->field("Query", "Status = 'new' OR ( Status = 'open' AND Subject LIKE 'office' )");
148     $agent->submit;
149     is( getQueryFromForm($agent),
150         "Status = 'new' OR ( Status = 'open' AND Subject LIKE 'office' )",
151         "no aggregators change"
152     );
153 }
154
155 # - new items go one level down
156 # - add items at currently selected level
157 # - if nothing is selected, add at end, one level down
158 #
159 # move left
160 # - error if nothing selected
161 # - same item should be selected after move
162 # - can't move left if you're at the top level
163 #
164 # move right
165 # - error if nothing selected
166 # - same item should be selected after move
167 # - can always move right (no max depth...should there be?)
168 #
169 # move up
170 # - error if nothing selected
171 # - same item should be selected after move
172 # - can't move up if you're first in the list
173 #
174 # move down
175 # - error if nothing selected
176 # - same item should be selected after move
177 # - can't move down if you're last in the list
178 #
179 # toggle
180 # - error if nothing selected
181 # - change all aggregators in the grouping
182 # - don't change any others
183 #
184 # delete
185 # - error if nothing selected
186 # - delete currently selected item
187 # - delete all children of a grouping
188 # - if delete leaves a node with no children, delete that, too
189 # - what should be selected?
190 #
191 # Clear
192 # - clears entire query
193 # - clears it from the session, too
194
195
196 # create a custom field with nonascii name and try to add a condition
197 {
198     my $cf = RT::CustomField->new( RT->SystemUser );
199     $cf->LoadByName( Name => "\x{442}", Queue => 0 );
200     if ( $cf->id ) {
201         is($cf->Type, 'Freeform', 'loaded and type is correct');
202     } else {
203         my ($return, $msg) = $cf->Create(
204             Name => "\x{442}",
205             Queue => 0,
206             Type => 'Freeform',
207         );
208         ok($return, 'created CF') or diag "error: $msg";
209     }
210
211     my $response = $agent->get($url."Search/Build.html?NewQuery=1");
212     ok( $response->is_success, "Fetched " . $url."Search/Build.html" );
213
214     ok($agent->form_name('BuildQuery'), "found the form once");
215     $agent->field("ValueOf'CF.{\x{442}}'", "\x{441}");
216     $agent->submit();
217     is( getQueryFromForm($agent),
218         "'CF.{\x{442}}' LIKE '\x{441}'",
219         "no changes, no duplicate condition with badly encoded text"
220     );
221
222 }
223
224 diag "input a condition, select (several conditions), click delete";
225 {
226     my $response = $agent->get( $url."Search/Edit.html" );
227     ok $response->is_success, "Fetched /Search/Edit.html";
228     ok $agent->form_name('BuildQueryAdvanced'), "found the form";
229     $agent->field("Query", "( Status = 'new' OR Status = 'open' )");
230     $agent->submit;
231     is( getQueryFromForm($agent),
232         "( Status = 'new' OR Status = 'open' )",
233         "query is the same"
234     );
235     $agent->select("clauses", [qw(0 1 2)]);
236     $agent->field( ValueOfid => 10 );
237     $agent->click("DeleteClause");
238
239     is( getQueryFromForm($agent),
240         "id < 10",
241         "replaced query successfuly"
242     );
243 }
244
245 diag "send query with not quoted negative number";
246 {
247     my $response = $agent->get($url."Search/Build.html?Query=Priority%20>%20-2");
248     ok( $response->is_success, "Fetched " . $url."Search/Build.html" );
249
250     is( getQueryFromForm($agent),
251         "Priority > -2",
252         "query is the same"
253     );
254 }
255
256 diag "click advanced, enter an invalid SQL IS restriction, apply and check that we corrected it";
257 {
258     my $response = $agent->get($url."Search/Edit.html");
259     ok( $response->is_success, "Fetched /Search/Edit.html" );
260     ok($agent->form_name('BuildQueryAdvanced'), "found the form");
261     $agent->field("Query", "Requestor.EmailAddress IS 'FOOBAR'");
262     $agent->submit;
263     is( getQueryFromForm($agent),
264         "Requestor.EmailAddress IS NULL",
265         "foobar is replaced by NULL"
266     );
267 }
268
269 diag "click advanced, enter an invalid SQL IS NOT restriction, apply and check that we corrected it";
270 {
271     my $response = $agent->get($url."Search/Edit.html");
272     ok( $response->is_success, "Fetched /Search/Edit.html" );
273     ok($agent->form_name('BuildQueryAdvanced'), "found the form");
274     $agent->field("Query", "Requestor.EmailAddress IS NOT 'FOOBAR'");
275     $agent->submit;
276     is( getQueryFromForm($agent),
277         "Requestor.EmailAddress IS NOT NULL",
278         "foobar is replaced by NULL"
279     );
280 }
281
282 diag "click advanced, enter a valid SQL, but the field is lower cased";
283 {
284     my $response = $agent->get($url."Search/Edit.html");
285     ok( $response->is_success, "Fetched /Search/Edit.html" );
286     ok($agent->form_name('BuildQueryAdvanced'), "found the form");
287     $agent->field("Query", "status = 'new'");
288     $agent->submit;
289     $agent->content_lacks( 'Unknown field:', 'no "unknown field" warning' );
290     is( getQueryFromForm($agent),
291         "Status = 'new'",
292         "field's case is corrected"
293     );
294 }
295
296 diag "make sure skipped order by field doesn't break search";
297 {
298     my $t = RT::Test->create_ticket( Queue => 'General', Subject => 'test' );
299     ok $t && $t->id, 'created a ticket';
300
301     $agent->get_ok($url."Search/Edit.html");
302     ok($agent->form_name('BuildQueryAdvanced'), "found the form");
303     $agent->field("Query", "id = ". $t->id);
304     $agent->submit;
305
306     $agent->follow_link_ok({id => 'page-results'});
307     ok( $agent->find_link(
308         text      => $t->id,
309         url_regex => qr{/Ticket/Display\.html},
310     ), "link to the ticket" );
311
312     $agent->follow_link_ok({id => 'page-edit_search'});
313     $agent->form_name('BuildQuery');
314     $agent->field("OrderBy", 'Requestor.EmailAddress', 3);
315     $agent->submit;
316     $agent->form_name('BuildQuery');
317     is $agent->value('OrderBy', 1), 'id';
318     is $agent->value('OrderBy', 2), '';
319     is $agent->value('OrderBy', 3), 'Requestor.EmailAddress';
320
321     $agent->follow_link_ok({id => 'page-results'});
322     ok( $agent->find_link(
323         text      => $t->id,
324         url_regex => qr{/Ticket/Display\.html},
325     ), "link to the ticket" );
326 }