File Coverage

blib/lib/Weasel.pm
Criterion Covered Total %
statement 16 17 94.1
branch 1 2 50.0
condition 1 3 33.3
subroutine 5 6 83.3
pod 2 2 100.0
total 25 30 83.3


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Weasel - Perl's php/Mink-inspired abstracted web-driver framework
5              
6             =head1 VERSION
7              
8             0.31
9              
10             =head1 SYNOPSIS
11              
12             use Weasel;
13             use Weasel::Session;
14             use Weasel::Driver::Selenium2;
15              
16             my $weasel = Weasel->new(
17             default_session => 'default',
18             sessions => {
19             default => Weasel::Session->new(
20             driver => Weasel::Driver::Selenium2->new(%opts),
21             ),
22             });
23              
24             $weasel->session->get('http://localhost/index');
25              
26             =head1 DESCRIPTION
27              
28             This module abstracts away the differences between the various
29             web-driver protocols, like the Mink project does for PHP.
30              
31             While heavily inspired by Mink, C<Weasel> aims to improve over it
32             by being extensible, providing not just access to the underlying
33             browser, yet to provide building blocks for further development
34             and abstraction.
35              
36             L<Pherkin::Extension::Weasel> provides integration with
37             L<Test::BDD::Cucumber> (aka pherkin), for BDD testing.
38              
39             For the actual page interaction, this module needs a driver to
40             be installed. Currently, that means L<Weasel::Driver::Selenium2>.
41             Other driver implementations, such as L<Sahi|http://sahipro.com/>
42             can be independently developed and uploaded to CPAN, or contributed.
43             (We welcome and encourage both!)
44              
45              
46             =head2 DIFFERENCES WITH OTHER FRAMEWORKS
47              
48             =over
49              
50             =item Mnemonics for element lookup patterns
51              
52             The central registry of xpath expressions to find common page elements
53             helps to keep page access code clean. E.g. compare:
54              
55             use Weasel::FindExpanders::HTML;
56             $session->page->find('*contains', text => 'Some text');
57              
58             With
59              
60             $session->page->find(".//*[contains(.,'Some text')]
61             [not(.//*[contains(.,'Some text')])]");
62              
63             Multiple patterns can be registered for a single mnemonic, which
64             will be concatenated to a single xpath expression to find the matching
65             tags in a single driver query.
66              
67             Besides good performance, this has the benefit that the following
68              
69             $session->page->find('*button', text => 'Click!');
70              
71             can be easily extended to match
72             L<Dojo toolkit's|http://dojotoolkit.org/documentation/> buttons, which
73             on the HTML level don't contain visible button or input tags, simply
74             by using the widget support set:
75              
76             use Weasel::Widgets::Dojo;
77              
78             =item Widgets encapsulate specific behaviours
79              
80             All elements in C<Weasel> are of the base type C<Weasel::Element>, which
81             encapsulates the regular element interactions (click, find children, etc).
82              
83             While most elements will be represented by C<Weasel::Element>, it's possible
84             to implement other wrappers. These offer a logical extension point to
85             implement tag-specific utility functions. E.g.
86             C<Weasel::Widgets::HTML::Select>, which adds the utility function
87             C<select_option>.
88              
89             These widgets also offer a good way to override default behaviours. One
90             such case is the Dojo implementation of a 'select' element. This element
91             replaces the select tag entirely and in contrast with the original, doesn't
92             keep the options as child elements of the 'select'-replacing tag. By using
93             the Dojo widget library
94              
95             use Weasel::Widget::Dojo;
96              
97             the lack of the parent/child relation between the the select and its options
98             is transparently handled by overriding the widget's C<find> and C<find_all>
99             methods.
100              
101             =back
102              
103             =cut
104              
105             =head1 DEPENDENCIES
106              
107              
108              
109             =cut
110              
111             package Weasel;
112              
113 2     2   559508 use strict;
  2         12  
  2         59  
114 2     2   10 use warnings;
  2         4  
  2         49  
115              
116 2     2   656 use Moose;
  2         472093  
  2         15  
117 2     2   15369 use namespace::autoclean;
  2         16902  
  2         8  
118              
119             our $VERSION = '0.31';
120              
121             # From https://w3c.github.io/webdriver/webdriver-spec.html#keyboard-actions
122             my %key_codes = (
123             NULL => "\N{U+E000}",
124             CANCEL => "\N{U+E001}",
125             HELP => "\N{U+E002}",
126             BACK_SPACE => "\N{U+E003}",
127             TAB => "\N{U+E004}",
128             CLEAR => "\N{U+E005}",
129             RETURN => "\N{U+E006}",
130             ENTER => "\N{U+E007}",
131             SHIFT => "\N{U+E008}",
132             CONTROL => "\N{U+E009}",
133             ALT => "\N{U+E00A}",
134             PAUSE => "\N{U+E00B}",
135             ESCAPE => "\N{U+E00C}",
136             SPACE => "\N{U+E00D}",
137             PAGE_UP => "\N{U+E00E}",
138             PAGE_DOWN => "\N{U+E00F}",
139             'END' => "\N{U+E010}",
140             HOME => "\N{U+E011}",
141             ARROW_LEFT => "\N{U+E012}",
142             ARROW_UP => "\N{U+E013}",
143             ARROW_RIGHT => "\N{U+E014}",
144             ARROW_DOWN => "\N{U+E015}",
145             INSERT => "\N{U+E016}",
146             DELETE => "\N{U+E017}",
147             SEMICOLON => "\N{U+E018}",
148             EQUALS => "\N{U+E019}",
149             NUMPAD0 => "\N{U+E01A}",
150             NUMPAD1 => "\N{U+E01B}",
151             NUMPAD2 => "\N{U+E01C}",
152             NUMPAD3 => "\N{U+E01D}",
153             NUMPAD4 => "\N{U+E01E}",
154             NUMPAD5 => "\N{U+E01F}",
155             NUMPAD6 => "\N{U+E020}",
156             NUMPAD7 => "\N{U+E021}",
157             NUMPAD8 => "\N{U+E022}",
158             NUMPAD9 => "\N{U+E023}",
159             MULTIPLY => "\N{U+E024}",
160             ADD => "\N{U+E025}",
161             SEPARATOR => "\N{U+E026}",
162             SUBTRACT => "\N{U+E027}",
163             DECIMAL => "\N{U+E028}",
164             DIVIDE => "\N{U+E029}",
165             F1 => "\N{U+E031}",
166             F2 => "\N{U+E032}",
167             F3 => "\N{U+E033}",
168             F4 => "\N{U+E034}",
169             F5 => "\N{U+E035}",
170             F6 => "\N{U+E036}",
171             F7 => "\N{U+E037}",
172             F8 => "\N{U+E038}",
173             F9 => "\N{U+E039}",
174             F10 => "\N{U+E03A}",
175             F11 => "\N{U+E03B}",
176             F12 => "\N{U+E03C}",
177             META => "\N{U+E03D}",
178             COMMAND => "\N{U+E03D}",
179             ZENKAKU_HANKAKU => "\N{U+E040}",
180             );
181              
182             =over
183              
184             =item KEYS
185              
186             Returns a reference to a hash with names of the keys in the
187             hash keys and single-character strings containing the key
188             codes as the values.
189              
190             =cut
191              
192             sub KEYS {
193 0     0 1 0 return \%key_codes;
194             }
195              
196             =back
197              
198             =head1 ATTRIBUTES
199              
200              
201             =over
202              
203             =item default_session
204              
205             The name of the default session to return from C<session>, in case
206             no name argument is provided.
207              
208             =cut
209              
210             has 'default_session' => (is => 'rw',
211             isa => 'Str',
212             default => 'default',
213             );
214              
215             =item sessions
216              
217             Holds the sessions registered with the C<Weasel> instance.
218              
219             =cut
220              
221             has 'sessions' => (is => 'ro',
222             isa => 'HashRef[Weasel::Session]',
223             default => sub { {} },
224             );
225              
226             =back
227              
228             =head1 SUBROUTINES/METHODS
229              
230             =over
231              
232             =item session([$name [, $value]])
233              
234             Returns the session identified by C<$name>.
235              
236             If C<$value> is specified, it's associated with the given C<$name>.
237              
238             =cut
239              
240             sub session {
241 1     1 1 7 my ($self, $name, $value) = @_;
242              
243 1   33     34 $name //= $self->default_session;
244 1 50       3 $self->sessions->{$name} = $value
245             if defined $value;
246              
247 1         22 return $self->sessions->{$name};
248             }
249              
250              
251             =back
252              
253             =head1 AUTHOR
254              
255             Erik Huelsmann
256              
257             =head1 CONTRIBUTORS
258              
259             Erik Huelsmann
260             Yves Lavoie
261              
262             =head1 MAINTAINERS
263              
264             Erik Huelsmann
265              
266             =head1 BUGS AND LIMITATIONS
267              
268             Bugs can be filed in the GitHub issue tracker for the Weasel project:
269             L<https://github.com/perl-weasel/weasel/issues>
270              
271             =head1 SOURCE
272              
273             The source code repository for Weasel is at
274             https://github.com/perl-weasel/weasel
275              
276             =head1 SUPPORT
277              
278             Community support is available through
279             L<perl-weasel@googlegroups.com|mailto:perl-weasel@googlegroups.com>.
280              
281             =head1 BUGS
282              
283             Bugs can be filed in the GitHub issue tracker for the Weasel project:
284             L<https://github.com/perl-weasel/weasel/issues>
285              
286             =head1 SOURCE
287              
288             The source code repository for Weasel is at
289             L<https://github.com/perl-weasel/weasel>
290              
291             =head1 SUPPORT
292              
293             Community support is available through
294             L<perl-weasel@googlegroups.com|mailto:perl-weasel@googlegroups.com>.
295              
296             =head1 LICENSE AND COPYRIGHT
297              
298             (C) 2016-2023 Erik Huelsmann
299              
300             Licensed under the same terms as Perl.
301              
302             =cut
303              
304              
305             __PACKAGE__->meta->make_immutable;
306              
307             1;
308