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