Almost-minimal filesystem based blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
6.5 KiB

  1. package Test::HTML::W3C;
  2. use strict;
  3. use vars qw($VERSION @EXPORT);
  4. $VERSION = "0.02";
  5. =head1 NAME
  6. Test::HTML::W3C - Perform W3C HTML validation testing
  7. =head1 SYNOPSIS
  8. use Test::W3C::HTML tests => $test_count;
  9. # or
  10. use Test::W3C::HTML 'show_detail';
  11. # or when using both
  12. use Test::W3C::HTML tests => $test_count, 'show_detail';
  13. is_valid_markup($my_html_scalar);
  14. is_valid_file("/path/to/my/file.html");
  15. is_valid("http://example.com");
  16. # Get the underlying WebService:;Validator::W3C::HTML object
  17. my $validator = validator();
  18. =head1 DESCRIPTION
  19. The purpose of this module is to provide a wide range of testing
  20. utilities. Various ways to say "ok" with better diagnostics,
  21. facilities to skip tests, test future features and compare complicated
  22. data structures. While you can do almost anything with a simple
  23. C<ok()> function, it doesn't provide good diagnostic output.
  24. =head1 ABUSE
  25. Please keep in mind that the W3C validation pages and services are
  26. a shared resource. If you plan to do many many tests, please consider
  27. using your own installation of the validation programs, and then use
  28. your local install by modifying the local validtor:
  29. my $v = validator();
  30. $v->validator_uri($my_own_validator);
  31. See the documentation for WebService:;Validator::W3C::HTML and the W3C's
  32. site at http://validator.w3.org/ for details
  33. =over 4
  34. =cut
  35. use WebService::Validator::HTML::W3C;
  36. use base qw(Test::Builder::Module);
  37. @EXPORT = qw(
  38. plan
  39. diag_html
  40. is_valid_markup
  41. is_valid_file
  42. is_valid
  43. validator
  44. );
  45. my $v = WebService::Validator::HTML::W3C->new();
  46. my $not_checked = 1;
  47. my $show_detail = 0;
  48. sub import_extra {
  49. my ($class, $list) = @_;
  50. my @other = ();
  51. my $idx = 0;
  52. while( $idx <= $#{$list} ) {
  53. my $item = $list->[$idx];
  54. if( defined $item and $item eq 'show_detail' ) {
  55. $show_detail = 1;
  56. $v = WebService::Validator::HTML::W3C->new(detailed => 1);
  57. } else {
  58. push @other, $item;
  59. }
  60. $idx++;
  61. }
  62. @$list = @other;
  63. }
  64. =item validator();
  65. B<Description:> Returns the underlying WebService::Validator::HTML::W3C object
  66. B<Parameters:> None.
  67. B<Returns:> $validator
  68. =cut
  69. sub validator {
  70. return $v;
  71. }
  72. =item plan();
  73. B<Description:> Returns the underlying WebService::Validator::HTML::W3C object
  74. B<Parameters:> None.
  75. B<Returns:> $validator
  76. =cut
  77. sub plan {
  78. __PACKAGE__->builder->plan(@_);
  79. }
  80. sub _check_plan {
  81. $not_checked = 0;
  82. if (! __PACKAGE__->builder->has_plan()) {
  83. plan("no_plan");
  84. }
  85. }
  86. =item is_valid_markup($markup[, $name]);
  87. B<Description:> is_valid_markup tests whether the text in the provided scalar
  88. value correctly validates according to the W3C specifications. This is useful
  89. if you have markup stored in a scalar that you wish to test that you might get
  90. from using LWP or WWW::Mechanize for example...
  91. B<Parameters:> $markup, a scalar containing the data to test, $name, an
  92. optional descriptive test name.
  93. B<Returns:> None.
  94. =cut
  95. sub is_valid_markup {
  96. _check_plan() if $not_checked;
  97. my ($markup, $message) = @_;
  98. if ($v->validate_markup($markup)) {
  99. _result($v, $message);
  100. } else {
  101. _validator_err($v, "markup");
  102. }
  103. }
  104. =item is_valid_file($path[, $name]);
  105. B<Description:> is_valid_file works the same way as is_valid_markup, except that
  106. you can specify the text to validate with the path to a filename. This is useful
  107. if you have pregenerated all your HTML files locally, and now wish to test them.
  108. B<Parameters:> $path, a scalar, $name, an optional descriptive test name.
  109. B<Returns:> None.
  110. =cut
  111. sub is_valid_file {
  112. my ($file, $message) = @_;
  113. _check_plan() if $not_checked;
  114. if ($v->validate_file($file)) {
  115. _result($v, $message);
  116. } else {
  117. _validator_err($v, "file");
  118. }
  119. }
  120. =item is_valid($url[, $name]);
  121. B<Description:> is_valid, again, works very similarly to the is_valid_file and
  122. is_valid_file, except you specify a document that is already online with its
  123. URL. This can be useful if you wish to periodically test a website or webpage
  124. that dynamically changes over time for example, like a blog or a wiki, without
  125. first saving the html to a file using your browswer, or a utility such as wget.
  126. B<Parameters:> $url, a scalar, $name, an optional descriptive test name.
  127. B<Returns:> None.
  128. =cut
  129. sub is_valid {
  130. my ($uri, $message) = @_;
  131. _check_plan() if $not_checked;
  132. if ($v->validate($uri)) {
  133. _result($v, $message);
  134. } else {
  135. _validator_err($v, "URI");
  136. }
  137. }
  138. sub _validator_err {
  139. my ($validator, $type) = @_;
  140. __PACKAGE__->builder->ok(0, "Failed to validate $type.");
  141. __PACKAGE__->builder->diag($v->validator_error());
  142. }
  143. sub _result {
  144. my ($validator, $message) = @_;
  145. if ($validator->is_valid()) {
  146. __PACKAGE__->builder->ok(1, $message);
  147. } else {
  148. my $num = $validator->num_errors();
  149. my $plurality = ($num == 1) ? "error" : "errors";
  150. __PACKAGE__->builder->ok(0, $message . " ($num $plurality).");
  151. }
  152. }
  153. =item diag_html($url);
  154. B<Description:> If you want to display the actual errors reported by
  155. the service for a particular test, you can use the diag_html function.
  156. Please note that you must have imported 'show_detail' for this to
  157. work properly.
  158. use Test::HTML::W3C 'show_detail';
  159. is_valid_markup("<html></html">, "My simple test") or diag_html();
  160. B<Parameters:> $url, a scalar.
  161. B<Returns:> None.
  162. =cut
  163. sub diag_html {
  164. my $tb = __PACKAGE__->builder();
  165. if ($show_detail) {
  166. my @errs = $v->errors();
  167. my $e;
  168. foreach my $error ( @{$v->errors()} ) {
  169. $e .= sprintf("%s at line %d\n", $error->msg, $error->line);
  170. }
  171. $tb->diag($e);
  172. } else {
  173. $tb->diag("You need to import 'show_detail' in order to call diag_html\n");
  174. }
  175. }
  176. 1;
  177. __END__
  178. =back
  179. =head1 SEE ALSO
  180. L<Test::Builder::Module> for creating your own testing modules.
  181. L<Test::More> for another popular testing framework, also based on
  182. Test::Builder
  183. L<Test::Harness> for detils about how test results are interpreted.
  184. =head1 AUTHORS
  185. Victor E<lt>victor73@gmail.comE<gt> with inspiration
  186. from the authors of the Test::More and WebService::Validator::W3C:HTML
  187. modules.
  188. =head1 BUGS
  189. See F<http://rt.cpan.org> to report and view bugs.
  190. =head1 COPYRIGHT
  191. Copyright 2006 by Victor E<lt>victor73@gmail.comE<gt>.
  192. This program is free software; you can redistribute it and/or
  193. modify it under the same terms as Perl itself.
  194. See F<http://www.perl.com/perl/misc/Artistic.html>