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