Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

HTML::Selector::XPath support (optional)

This adds 2 new attributes to ->new:

css_selector => 1 means that any paths passed to ok/is/etc will
first be transformed by HTML::Selector::XPath (if it is available,
or the script will die).

path_generator => sub { ... } allows people to pass a custom sub
to generate XPaths from the string passed, which may come in
handy for someone
  • Loading branch information...
commit d8086323cbdf8294ca27cd515fe63f3557c116ed 1 parent aa8c308
Oliver Charles authored
Showing with 48 additions and 10 deletions.
  1. +13 −9 Build.PL
  2. +35 −1 lib/Test/XPath.pm
View
22 Build.PL
@@ -5,27 +5,31 @@ use Module::Build;
Module::Build->new(
module_name => 'Test::XPath',
license => 'perl',
- configure_requires => {
- 'Module::Build' => '0.30',
- },
+ configure_requires => { 'Module::Build' => '0.30', },
build_requires => {
'Module::Build' => '0.30',
'Test::More' => '0.70',
},
- requires => {
+ requires => {
'Test::Builder' => '0.70',
'XML::LibXML' => '1.69',
'perl' => 5.006002,
},
- recommends => {
+ recommends => {
'Test::Pod' => '1.20',
'Test::Pod::Coverage' => '1.06',
},
- meta_merge => {
+ auto_features => {
+ selectors => {
+ description => 'CSS selectors support',
+ requires => { 'HTML::Selector::XPath' => '0.03', }
+ }
+ },
+ meta_merge => {
resources => {
- homepage => 'http://search.cpan.org/dist/Test-XPath/',
- bugtracker => 'http://github.com/theory/test-xpath/issues/',
- repository => 'http://github.com/theory/test-xpath/tree/',
+ homepage => 'http://search.cpan.org/dist/Test-XPath/',
+ bugtracker => 'http://github.com/theory/test-xpath/issues/',
+ repository => 'http://github.com/theory/test-xpath/tree/',
}
},
)->create_build_script;
View
36 lib/Test/XPath.pm
@@ -19,6 +19,8 @@ sub new {
return bless {
xpc => $xpc,
node => $doc->documentElement,
+ gen => $p{xpath_generator}
+ || ($p{css_selector} ? \&_css_selector : sub { shift })
};
}
@@ -26,6 +28,7 @@ sub ok {
my ($self, $xpath, $code, $desc) = @_;
my $xpc = $self->{xpc};
my $Test = Test::Builder->new;
+ $xpath = $self->{gen}->($xpath);
# Code and desc can be reversed, to support PerlX::MethodCallWithBlock.
($code, $desc) = ($desc, $code) if ref $desc eq 'CODE';
@@ -54,6 +57,7 @@ sub ok {
sub not_ok {
my ($self, $xpath, $desc) = @_;
+ $xpath = $self->{gen}->($xpath);
my $Test = Test::Builder->new;
$Test->ok( !$self->{xpc}->exists($xpath, $self->{node}), $desc);
}
@@ -69,7 +73,7 @@ sub xpc { shift->{xpc} }
sub _findv {
my $self = shift;
- $self->{xpc}->findvalue(shift, $self->{node});
+ $self->{xpc}->findvalue($self->{gen}->(shift), $self->{node});
}
sub _doc {
@@ -104,6 +108,14 @@ sub _doc {
);
}
+sub _css_selector {
+ my $path = shift;
+ eval 'require HTML::Selector::XPath';
+ die "Please install HTML::Selector::XPath to use CSS selectors"
+ if $@;
+ return HTML::Selector::XPath->new($path)->to_xpath;
+}
+
# Add Test::XML::XPath compatibility?
# sub like_xpath($$;$) { __PACKAGE__->new( xml => shift )->ok( @_ ) }
# sub unlike_xpath($$;$) { __PACKAGE__->new( xml => shift )->not_ok( @_ ) }
@@ -365,6 +377,28 @@ L<XML::LibXML::Parser options|XML::LibXML::Parser/"PARSER OPTIONS">, such as
"validation", "recover", and "no_network". These can be useful for tweaking
the behavior of the parser.
+=item C<css_selector>
+
+ css_selector => 1,
+
+Any paths passed to ok(), is() etc will be first preprocessed by
+HTML::Selector::XPath. This allows you to use CSS selector syntax, which can
+be more compact for simple expressions. For example:
+
+ $tx->is('div#content div.article h1', '...')
+
+Is equivilent to:
+
+ $tx->is('//div[@id="content"]//div[@class="article"]//h1', '...')
+
+=item C<path_generator>
+
+ path_generator => sub { my $xpath = shift; }
+
+Allows a subroutine reference to be passed in, which will be used whenever a XPath
+is required. This allows you to transform the XPath, for example you may have
+some custom syntax which is much more concise than an XPath.
+
=back
=head1 Instance Interface
Please sign in to comment.
Something went wrong with that request. Please try again.