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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
package FixMyStreet::TestMech;
use base qw(Test::WWW::Mechanize::Catalyst Test::Builder::Module);
use strict;
use warnings;
BEGIN {
use FixMyStreet;
FixMyStreet->test_mode(1);
}
use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App';
use Test::More;
use Web::Scraper;
use Carp;
=head1 NAME
FixMyStreet::TestMech - T::WWW::M:C but with FMS specific smarts
=head1 DESCRIPTION
This module subclasses L<Test::WWW::Mechanize::Catalyst> and adds some
FixMyStreet specific smarts - such as the ability to scrape the resulting page
for form error messages.
Note - using this module puts L<FixMyStreet::App> into test mode - so for
example emails will not get sent.
=head1 METHODS
=head2 check_not_logged_in, check_logged_in
$bool = $mech->check_not_logged_in();
$bool = $mech->check_logged_in();
Check that the current mech is not logged or logged in as a user. Produces test output.
Returns true test passed, false otherwise.
=cut
sub not_logged_in_ok {
my $mech = shift;
$mech->builder->ok( $mech->get('/auth/check_auth')->code == 401,
"not logged in" );
}
sub logged_in_ok {
my $mech = shift;
$mech->builder->ok( $mech->get('/auth/check_auth')->code == 200,
"logged in" );
}
=head2 log_out_ok
$bool = $mech->log_out_ok( );
Log out the current user
=cut
sub log_out_ok {
my $mech = shift;
$mech->get_ok('/auth/logout');
$mech->not_logged_in_ok;
}
=head2 form_errors
my $arrayref = $mech->form_errors;
Find all the form errors on the current page and return them in page order as an
arrayref of TEXTs. If none found return empty arrayref.
=cut
sub form_errors {
my $mech = shift;
my $result = scraper {
process 'div.form-error', 'errors[]', 'TEXT';
}
->scrape( $mech->response );
return $result->{errors} || [];
}
=head2 pc_alternatives
my $arrayref = $mech->pc_alternatives;
Find all the suggestions for near matches for a location. Return text presented to user as arrayref, empty arrayref if none found.
=cut
sub pc_alternatives {
my $mech = shift;
my $result = scraper {
process 'ul.pc_alternatives li', 'pc_alternatives[]', 'TEXT';
}
->scrape( $mech->response );
return $result->{pc_alternatives} || [];
}
=head2 extract_location
$hashref = $mech->extract_location( );
Extracts the location from the current page. Looks for inputs with the names
C<pc>, C<latitude> and C<longitude> and returns their values in a hashref with
those keys. If no values found then the values in hashrof are C<undef>.
=cut
sub extract_location {
my $mech = shift;
my $result = scraper {
process 'input[name="pc"]', pc => '@value';
process 'input[name="latitude"]', latitude => '@value';
process 'input[name="longitude"]', longitude => '@value';
}
->scrape( $mech->response );
return {
pc => undef,
latitude => undef,
longitude => undef,
%$result
};
}
=head2 visible_form_values
$hashref = $mech->visible_form_values( );
Return all the visible form values on the page - ie not the hidden ones.
=cut
sub visible_form_values {
my $mech = shift;
my @forms = $mech->forms;
# insert form filtering here (eg ignore login form)
croak "Found no forms - can't continue..."
unless @forms;
croak "Found several forms - don't know which to use..."
if @forms > 1;
my $form = $forms[0];
my @visible_fields =
grep { ref($_) ne 'HTML::Form::SubmitInput' }
grep { ref($_) ne 'HTML::Form::ImageInput' }
grep { ref($_) ne 'HTML::Form::TextInput' || $_->type ne 'hidden' }
$form->inputs;
my @visible_field_names = map { $_->name } @visible_fields;
my %params = map { $_ => $form->value($_) } @visible_field_names;
return \%params;
}
1;
|