libtap-formatter-html-perl-0.11+dfsg.orig/0000755000175000017500000000000012076716223017513 5ustar salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/Changes0000444000175000017500000001066012076610727021011 0ustar salvisalviRevision history for 'TAP-Formatter-HTML' Perl module ----------------------------------------------------- All changes by Steve Purkis, unless otherwise noted. 0.11 + fixed RT #81922: tests no longer hang on Win32. Didn't get to the bottom of the issue (likely IPC::Open3 & redirecting STDOUT not playing nicely), but worked around it. + fixed a bug on Win32 where default js_uris & css_uris were being mangled: "C:%5C..." vs "C:\". May have affected other Win32 URIs too. 0.10 + fixed RT #82738: color method was not implemented. + fixed RT #74364: TT2 INCLUDE_PATH no longer set to all dirs in @INC, now it is set to parent directory TAP::Formatter::HTML was loaded from. 0.09 + upgraded to jQuery 1.4.2 + updated App::Prove::Plugin::HTML to simplify cmdline usage to the extent possible. + fixed RT #41457 & RT #49621: applied Neil Hemingway, Tim Esselens, and Panu Ervamaa's patches, and got everything working. This addresses: + small changes to the top-left corner menu (default_report.css) to render it corretly with Firefox 3 (Linux) + inline_js fix + added support for force_inline_js (not on by default, including jQuery inline causes errors) + fixed bug in handling of parse_errors in default_report.tt + fixed bug: nothing happens when I click on the test output. + XHTML support + fixed bug: click on summary changes location + fixed 2 minor javascript bugs where '#' was being used as a jQuery id ref + added new feature: column sorting via Christian Bach's jquery.tablesorter plugin (bundled from http://tablesorter.com). optional. + added new feature: up to top of test when the test filename is no longer visible. 0.08 + applied Steffen Schwigon's patch to display YAML TAP as pre-formatted text. + fixed RT #43871: missing dep on File::Temp 0.17 [reported by Paddy Newman] + fixed RT #37983: CSS and JS Paths on Win32 get mangled and documented solution. [reported by Chris Davaz] + wrote some selenium tests, finally. found & fixed small bug where a test's html_id wasn't being set. + fixed RT #48296: pod for js_uris mentions styles, not scripts [reported by Slaven Rezić] + started on RT #41457: only got "incline_js" fixed [reported by Neil Hemingway] 0.07 + you can now specify an output file for the HTML to be written to! + you can now set some config params using environment vars. this should make it easier to configure without having to write custom code. + started writing an App::Prove plugin + fixed RT #40306: Typo in TAP::Formatter::HTML (incline_js) (also reported by Nathan S. Watson-Haigh) + applied patch from Michael Hendricks (who's work on this was sponsored by Grant Street Group) for a bug he & others identified: If tests are aggregated in multiple phases (per http://xrl.us/bedfih), ... the HTML output shows only the results from the final phase. + finally wrote some more tests, though selenium tests still not done + fixed RT #41411: fails on empty directory * started using IO::* modules for stdout & output_fh 0.06 + fixed RT #37019: tempdir without cleanup [reported by Steffen Schwigon] 0.05 + fixed width issue: test files with hundreds of tests were causing uncontrollable width in summary, making the report pretty annoying to read. + added toggle to display all / failed tests [requested by Alex Monney] + highlight failed test file names + reduced the size of generated HTML by a further ~10-35% (depending on the number of tests you run): * set test title on mouse-over so it's included only once * moved inline JS out of default_report.tt2 to its own file that is included by default. * split css into 'page' & 'report' for ease of user maintainability. [requested by Steffen Schwigon] + fixed bug: % passed on test file != % ok, was really confusing people. [requested by Wolfram Pfeiffer] * upgraded to jquery-1.2.6 0.04 + reduced the size of the generated HTML (by 25% on avg for my tests): * added 'minify' option to strip leading tabs * used short css class names * used numeric html id's * got rid of some other unnecessary whitespace 0.03 + updated deps in Build.PL (again, *sigh*) 0.02 + updated deps in Build.PL + wrote more docs, fixed a few errors & omissions - removed bin/runtests_html (it was added before I found out about 'prove') 0.01 + created Thurs May 14 2008 libtap-formatter-html-perl-0.11+dfsg.orig/META.yml0000444000175000017500000000161212076610727020764 0ustar salvisalvi--- abstract: 'TAP Test Harness output delegate for html output' author: - 'Steve Purkis ' build_requires: Module::Build: 0.20 Test::More: 0.01 configure_requires: Module::Build: 0.38 dynamic_config: 1 generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.113640' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: TAP-Formatter-HTML provides: App::Prove::Plugin::HTML: file: lib/App/Prove/Plugin/HTML.pm version: 0.11 TAP::Formatter::HTML: file: lib/TAP/Formatter/HTML.pm version: 0.11 TAP::Formatter::HTML::Session: file: lib/TAP/Formatter/HTML/Session.pm version: 0.11 requires: File::Temp: 0.17 TAP::Parser: 3.10 Template: 2.14 Test::Harness: 3.17 URI: 1.35 accessors: 0.02 perl: v5.6.0 resources: license: http://dev.perl.org/licenses/ version: 0.11 libtap-formatter-html-perl-0.11+dfsg.orig/Build.PL0000444000175000017500000000200112076610727021000 0ustar salvisalvi#!/usr/bin/perl =head1 NAME Build.PL - Build script generator for C module =head1 SYNOPSIS perl Build.PL ./Build ./Build test ./Build install =cut use strict; use warnings; use Module::Build; my $build = Module::Build->new ( module_name => 'TAP::Formatter::HTML', dist_version_from => 'lib/TAP/Formatter/HTML.pm', create_makefile_pl => 'passthrough', create_readme => 1, license => 'perl', requires => { 'perl' => '5.6.0', 'accessors' => '0.02', 'URI' => '1.35', 'Template' => '2.14', 'TAP::Parser' => '3.10', 'File::Temp' => '0.17', 'Test::Harness' => '3.17', }, build_requires => { 'Test::More' => '0.01', 'Module::Build' => '0.20', }, ); $build->add_build_element("tt2"); $build->add_build_element("css"); $build->add_build_element("js"); $build->create_build_script; __END__ =head1 AUTHOR Steve Purkis =cut libtap-formatter-html-perl-0.11+dfsg.orig/t/0000755000175000017500000000000012076610727017760 5ustar salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/t/30_tap_harness_compat.t0000444000175000017500000000046212076610727024321 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use TAP::Harness; use TAP::Formatter::HTML; # RT #82738: required TAP::Harness formatter method not available... eval { TAP::Formatter::HTML->new->color(1); }; my $e = $@; ok(!$e, 'no error on color') || diag($e); libtap-formatter-html-perl-0.11+dfsg.orig/t/99_test_pod.t0000444000175000017500000000020112076610727022276 0ustar salvisalviuse Test::More; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); libtap-formatter-html-perl-0.11+dfsg.orig/t/selenium/0000755000175000017500000000000012076610727021601 5ustar salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/t/selenium/server.pl0000444000175000017500000000267612076610727023455 0ustar salvisalviuse strict; use warnings; use Alien::SeleniumRC; my $sel_rc_port = $ENV{SELENIUM_RC_PORT} || 4446; my $sel_rc_args = "-singleWindow -port $sel_rc_port"; my $sel_rc = Alien::SeleniumRC::Server->new( $sel_rc_args ); $sel_rc->start; while (1) { print "type 'q' to quit\n"; my $i = <>; last if ($i =~ /q/); } $sel_rc->stop; warn "hack alert: you'll likely need to kill the java process running selenium\n"; BEGIN{ package Alien::SeleniumRC::Server; use Carp qw( croak ); use Test::More; sub new { my ($class, $sel_arg) = @_; my $self = { sel_arg => $sel_arg }; return bless $self, $class; } sub start { my ($self) = @_; # fork off a SeleniumRC server if (0 == ($self->{pid} = fork())){ local $SIG{TERM} = sub { diag("SeleniumRC server $$ going down (TERM)"); exit 0; }; diag("Starting SeleniumRC in $$"); Alien::SeleniumRC::start($self->{sel_arg}) or croak "Can't start SeleniumRC server: $!"; diag("SeleniumRC server $$ going down"); exit 1; } return $self->{pid}; } sub stop { my ($self) = @_; if ($self->{pid} and kill(0, $self->{pid})) { diag("Stopping SeleniumRC " . $self->{pid}); kill( 'TERM', $self->{pid} ); sleep 1; if (kill(0, $self->{pid})) { diag("Killing SeleniumRC " . $self->{pid}); kill( 'KILL', $self->{pid} ); } } } sub DESTROY { my ($self) = @_; $self->stop if ($self->{pid}); } 1; } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/0000755000175000017500000000000012076610727020671 5ustar salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/t/data/01_pass.pl0000444000175000017500000000067412076610727022501 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); TODO: { local $TODO = 'just cant get these working?'; is(1, 2, 'one is two?'); like('abc', qr/d/, 'contains d?'); } SKIP: { skip 'to the loo', 2; ok(2, 'youre ok'); fail('dont run me'); } TODO: { todo_skip 'to the loo again', 2; ok(2, 'were ok'); fail('really dont run me'); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/11_lots_of_tests.pl0000444000175000017500000000022012076610727024406 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; for my $i (1..500) { # chuck in some failures ok( $i % 11, "$i % 11 is true" ); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/03_plan_fail.pl0000444000175000017500000000020212076610727023445 0ustar salvisalviuse strict; use warnings; use Test::More tests => 2; ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); libtap-formatter-html-perl-0.11+dfsg.orig/t/data/07_todo_pass.pl0000444000175000017500000000053412076610727023527 0ustar salvisalviuse strict; use warnings; use Test::More tests => 7; ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); TODO: { local $TODO = 'just cant get these working?'; is(1, 1, 'one is one!'); like('abc', qr/c/, 'contains c?'); } TODO: { todo_skip 'to the loo', 2; ok(2, 'youre ok'); fail('dont run me'); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/06_skip_all.pl0000444000175000017500000000013612076610727023327 0ustar salvisalviuse strict; use warnings; use Test::More skip_all => 'likity skipity'; fail('dont run me'); libtap-formatter-html-perl-0.11+dfsg.orig/t/data/05_compile_fail.pl0000444000175000017500000000036612076610727024160 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; it'd all be ok, except I'm writting some silly comment here without actually remembering to put the # comment in... ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); libtap-formatter-html-perl-0.11+dfsg.orig/t/data/08_html_in_output.pl0000444000175000017500000000040412076610727024603 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; ok(1, 'escape some of these chars: !@#$%^++_)(*&^%$#@!><'); like('ac', qr//, 'contains in the '); is('ac', '

eeek

', ' in the diag messages..'); libtap-formatter-html-perl-0.11+dfsg.orig/t/data/02_fail.pl0000444000175000017500000000037612076610727022446 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); { is(1, 2, 'one is two?'); like('abc', qr/d/, 'contains d?'); } { ok(2, 'youre ok'); fail('dont run me'); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/09_skip_error.pl0000444000175000017500000000024012076610727023707 0ustar salvisalviuse strict; use warnings; use Test::More 'no_plan'; # don't define a SKIP label { skip 'to the loo', 2; ok(2, 'youre ok'); fail('dont run me'); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/10_todo_skip.pl0000444000175000017500000000022012076610727023511 0ustar salvisalviuse strict; use warnings; use Test::More tests => 2; TODO: { todo_skip 'to the loo', 2; ok(2, 'youre ok'); fail('dont run me'); } libtap-formatter-html-perl-0.11+dfsg.orig/t/data/04_die_fail.pl0000444000175000017500000000027012076610727023262 0ustar salvisalviuse strict; use warnings; use Test::More tests => 3; ok(1, 'im ok'); is(1, 1, 'one is one'); like('abc', qr/b/, 'contains b'); die "this is an error test, not some horrible error"; libtap-formatter-html-perl-0.11+dfsg.orig/t/02_escape_output.t0000444000175000017500000000163712076610727023333 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $stdout_fh = FileTempTFH->new; my $stdout_orig_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) or die "Error opening STDOUT for writing: $!"; STDOUT->fdopen( fileno($stdout_fh), 'w' ) or die "Error re-directing STDOUT: $!"; # Only run 1 test or tests will hang on Windows (RT #81922) my @tests = ( 't/data/01_pass.pl' ); my $f = TAP::Formatter::HTML->new({ escape_output => 1, force_inline_css => 0 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); STDOUT->fdopen( fileno($stdout_orig_fh), 'w' ) or die "Error resetting STDOUT: $!"; my $stdout = $stdout_fh->get_all_output || ''; isnt( $stdout, '', 'should be lots of output to stdout' ); ok( $stdout =~ /^# ok 1 - im ok/ms, 'found an escaped line of output' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/07_multiple_aggregate.t0000444000175000017500000000135712076610727024320 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use TAP::Parser::Aggregator; use_ok( 'TAP::Formatter::HTML' ); my $tmp = FileTempTFH->new; my $f = TAP::Formatter::HTML->new({ silent => 1 })->output_fh( $tmp )->force_inline_css(0); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); my $a = TAP::Parser::Aggregator->new; $a->start; $h->aggregate_tests( $a, 't/data/01_pass.pl' ); $h->aggregate_tests( $a, 't/data/02_fail.pl' ); $a->stop; $f->summary( $a ); my $html = $tmp->get_all_output; ok( $html =~ qr|01_pass|, 'html contains file 1' ); ok( $html =~ qr|02_fail|, 'html contains file 2' ); like( $html, qr|2 files|, '2 files processed' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/04_really_quiet.t0000444000175000017500000000155312076610727023151 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $stdout_fh = FileTempTFH->new; my $stdout_orig_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) or die "Error opening STDOUT for writing: $!"; STDOUT->fdopen( fileno($stdout_fh), 'w' ) or die "Error re-directing STDOUT: $!"; my @tests = ( 't/data/01_pass.pl', 't/data/02_fail.pl' ); my $f = TAP::Formatter::HTML->new({ escape_output => 1, really_quiet => 1, force_inline_css => 0 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); STDOUT->fdopen( fileno($stdout_orig_fh), 'w' ) or die "Error resetting STDOUT: $!"; my $stdout = $stdout_fh->get_all_output || ''; like( $stdout, qr|\A\s*<.+/html>\s*\Z|ms, 'should be no output to stdout other than HTML report' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/selenium_basic.t0000444000175000017500000002074512076610727023135 0ustar salvisalviuse lib 't/lib'; use strict; use warnings; use Test::More; BEGIN { eval "use Test::WWW::Selenium;"; if (my $e = $@) { plan skip_all => "Test::WWW::Selenium is required"; } } use URI::file; use Time::HiRes qw( sleep ); use FileTempTFH; use TAP::Harness; use TAP::Formatter::HTML; my $sel_rc_port = $ENV{SELENIUM_RC_PORT} || 4446; my $sel_speed = $ENV{SELENIUM_SPEED}; #my $sel_rc_args = "-singleWindow -port $sel_rc_port"; #my $sel_rc = Alien::SeleniumRC::Server->new( $sel_rc_args ); #$sel_rc->start; my $tmp = FileTempTFH->new; my $output_uri = URI::file->new( $tmp->filename ); my $sel; eval { $sel = Test::WWW::Selenium ->new( host => "localhost", port => $sel_rc_port, browser => "*firefox", browser_url => $output_uri, default_names => 1 ); }; if (my $e = $@) { plan skip_all => "Couldn't connect to SeleniumRC on $sel_rc_port: " . "try 'sudo perl t/selenium/server.pl'"; } plan 'no_plan'; # generate some test output: my $f = TAP::Formatter::HTML->new({ silent => 1, output_fh => $tmp, force_inline_css => 0 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); my @tests = glob( 't/data/*.pl' ); $h->runtests(@tests); my $crappy_wait_time = 0.450; $sel->open_ok($output_uri); $sel->wait_for_page_to_load_ok(5000); my $loc = $sel->get_location; $sel->set_speed( $sel_speed ) if $sel_speed; # test summary { $sel->text_is("//div[\@id='summary']/a", 'FAILED', 'summary text' ); $sel->hi_click_ok("//div[\@id='summary']/a", 'click summary link' ); $sel->location_is($loc, "click summary link shouldn't change location"); } # test show/hide failed: { # TODO: check for visible sections: $sel->is_visible_ok("//tr[\@id='t-data-01-pass-pl']", '01_pass visible'); $sel->is_visible_ok("//tr[\@id='t-data-02-fail-pl']", '02_fail visible'); $sel->hi_click_ok("link=show failed"); sleep( $crappy_wait_time ); ok( !$sel->is_visible("//tr[\@id='t-data-01-pass-pl']"), '01_pass now hidden' ); $sel->is_visible_ok("//tr[\@id='t-data-02-fail-pl']", '02_fail still visible'); $sel->hi_click_ok("link=show all"); sleep( $crappy_wait_time ); $sel->is_visible_ok("//tr[\@id='t-data-01-pass-pl']", '01_pass visible again'); $sel->is_visible_ok("//tr[\@id='t-data-02-fail-pl']", '02_fail still visible'); } $sel->open_ok($output_uri); $sel->wait_for_page_to_load_ok(5000); # test for 01_pass { $sel->attribute_is("//li[\@id='t0']\@class", "tst k"); $sel->attribute_is("//a[contains(\@href, '#t0')]/..\@class", "k p"); $sel->attribute_is("//li[\@id='t3']\@class", "tst t"); $sel->attribute_is("//a[contains(\@href, '#t3')]/..\@class", "t p"); $sel->attribute_is("//li[\@id='t5']\@class", "tst s"); $sel->attribute_is("//a[contains(\@href, '#t5')]/..\@class", "s p"); $sel->is_element_present_ok("//tr[\@id='t-data-01-pass-pl']/td/div/ul/li[\@class='cmt']"); $sel->is_element_present_ok("//tr[\@id='t-data-01-pass-pl']/td/div/ul/li[\@class='pln']"); # show test detail ok( !$sel->is_visible("//tr[\@id='t-data-01-pass-pl']/td/div[\@class='test-detail']"), '01_pass detail hidden' ); $sel->hi_click_ok("link=t/data/01_pass.pl"); sleep( $crappy_wait_time ); $sel->is_visible_ok ("//tr[\@id='t-data-01-pass-pl']/td/div[\@class='test-detail']", '01_pass detail now visible' ); # hide test detail $sel->hi_click_ok("link=t/data/01_pass.pl"); sleep( $crappy_wait_time ); ok( !$sel->is_visible("//tr[\@id='t-data-01-pass-pl']/td/div[\@class='test-detail']"), '01_pass detail hidden again' ); } # test 02_fail { $sel->attribute_is("//li[\@id='t12']\@class", "tst n"); $sel->attribute_is("//a[contains(\@href, '#t12')]/..\@class", "n f"); $sel->is_element_present_ok("//tr[\@id='t-data-02-fail-pl']/td/div/ul/li[\@class='cmt']"); $sel->is_element_present_ok("//tr[\@id='t-data-02-fail-pl']/td/div/ul/li[\@class='pln']"); ok(!$sel->is_element_present("//tr[\@id='t-data-02-fail-pl']/td/div/ul[\@class='parse-errors']/li"), 'no parse errors'); ok(!$sel->is_visible("//tr[\@id='t-data-02-fail-pl']/td/div[\@class='test-detail']"), '02_fail detail hidden'); # show & highlight a particular test $sel->hi_click_ok("//a[contains(\@href, '#t12')]"); sleep( $crappy_wait_time ); # $sel->attribute_is("//li[\@id='t12']\@style", "background-color: yellow;"); $sel->is_visible_ok("//tr[\@id='t-data-02-fail-pl']/td[2]/div[\@class='test-detail']"); # hide again $sel->hi_click_ok("link=t/data/02_fail.pl"); sleep( $crappy_wait_time ); ok(! $sel->is_visible("//tr[\@id='t-data-02-fail-pl']/td/div[\@class='test-detail']"), '02_fail detail hidden again'); } # test 03_plan_fail { $sel->attribute_is("//li[\@id='t18']\@class", "tst k unp"); $sel->attribute_is("//a[contains(\@href, '#t18')]/..\@class", "k f"); $sel->is_element_present_ok("//tr[\@id='t-data-03-plan-fail-pl']/td/div/ul/li[\@class='cmt']"); $sel->is_element_present_ok("//tr[\@id='t-data-03-plan-fail-pl']/td/div/ul/li[\@class='pln']"); $sel->is_element_present_ok("//tr[\@id='t-data-03-plan-fail-pl']/td/div/ul[\@class='parse-errors']/li"); $sel->hi_click_ok("link=t/data/03_plan_fail.pl"); sleep( $crappy_wait_time ); $sel->is_visible_ok("//tr[\@id='t-data-03-plan-fail-pl']/td[2]/div[\@class='test-detail']"); } # test 04_die_fail { $sel->is_element_present_ok("//tr[\@id='t-data-04-die-fail-pl']/td/div/ul/li[\@class='cmt']"); $sel->is_element_present_ok("//tr[\@id='t-data-04-die-fail-pl']/td/div/ul/li[\@class='pln']"); $sel->is_element_present_ok("//tr[\@id='t-data-04-die-fail-pl']/td/div/ul/li[\@class='unk']"); $sel->hi_click_ok("link=t/data/04_die_fail.pl"); sleep( $crappy_wait_time ); } # test 05_compile_fail { $sel->is_element_present_ok("//tr[\@id='t-data-05-compile-fail-pl']/td/div/ul/li[\@class='cmt']"); ok(! $sel->is_element_present("//tr[\@id='t-data-05-compile-fail-pl']/td/div/ul/li[\@class='pln']"), 'no test plan' ); $sel->is_element_present_ok("//tr[\@id='t-data-05-compile-fail-pl']/td/div/ul[\@class='parse-errors']/li"); # show & highlight a particular test ok(! $sel->is_visible("//tr[\@id='t-data-05-compile-fail-pl']/td[2]/div[\@class='test-detail']"), '05_compile_fail detail hidden' ); $sel->highlight_ok("//a[contains(\@title, 'No tests run!')]"); $sel->hi_click_ok("//a[contains(\@title, 'No tests run!')]"); sleep( $crappy_wait_time ); $sel->location_is($loc); $sel->is_visible_ok("//tr[\@id='t-data-05-compile-fail-pl']/td[2]/div[\@class='test-detail']"); # hide again $sel->hi_click_ok("link=t/data/05_compile_fail.pl"); sleep( $crappy_wait_time ); ok(! $sel->is_visible("//tr[\@id='t-data-05-compile-fail-pl']/td[2]/div[\@class='test-detail']"), '05_compile_fail detail hidden again' ); } # test 06_skip_all { $sel->is_element_present_ok("//tr[\@id='t-data-06-skip-all-pl']/td/div/ul/li[\@class='pln']"); # show & highlight a particular test ok(! $sel->is_visible("//tr[\@id='t-data-06-skip-all-pl']/td[2]/div[\@class='test-detail']"), '06_skip_all detail hidden' ); $sel->hi_click_ok("//tr[\@id='t-data-06-skip-all-pl']/td[\@class='results']//a"); sleep( $crappy_wait_time ); $sel->location_is($loc); $sel->is_visible_ok("//tr[\@id='t-data-06-skip-all-pl']/td[2]/div[\@class='test-detail']"); # hide again $sel->hi_click_ok("link=t/data/06_skip_all.pl"); sleep( $crappy_wait_time ); ok(! $sel->is_visible("//tr[\@id='t-data-06-skip-all-pl']/td[2]/div[\@class='test-detail']"), '06_skip_all detail hidden again' ); } # test 07_todo_pass { $sel->attribute_is("//li[\@id='t25']\@class", "tst u"); ok(! $sel->is_visible("//tr[\@id='t-data-07-todo-pass-pl']/td[2]/div[\@class='test-detail']"), '07_todo_pass detail hidden' ); $sel->hi_click_ok("//a[contains(\@href, '#t25')]"); sleep( $crappy_wait_time ); $sel->is_visible_ok("//tr[\@id='t-data-07-todo-pass-pl']/td[2]/div[\@class='test-detail']"); } # test 08_html_in_output { $sel->hi_click_ok("//a[contains(\@href, '#t31')]"); local $TODO = 'selenium returns this back to us w/HTML entities decoded'; $sel->text_like("//li[\@id='t31']", qr/<html>/, 'embedded html' ); } # test 09_skip_error { $sel->hi_click_ok("link=t/data/09_skip_error.pl"); } # test 11_lots_of_tests { $sel->hi_click_ok("//a[contains(\@href, '#t519')]"); } # Laziness sub Test::WWW::Selenium::hi_click_ok { my ($self, $id, $msg) = @_; $self->highlight_ok($id, $msg); $self->click_ok($id, $msg); } libtap-formatter-html-perl-0.11+dfsg.orig/t/03_silent.t0000444000175000017500000000300012076610727021734 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $output_fh = FileTempTFH->new; my $stdout_fh = FileTempTFH->new; my $stdout_orig_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) or die "Error opening STDOUT for writing: $!"; STDOUT->fdopen( fileno($stdout_fh), 'w' ) or die "Error re-directing STDOUT: $!"; # Note: strangely this doesn't fail on Windows, even though we're # running 2 tests... worth pointing out it may be due to lack of # output... my @tests = ( 't/data/01_pass.pl', 't/data/02_fail.pl' ); { my $f = TAP::Formatter::HTML->new({ escape_output => 1, silent => 1 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); my $stdout = $stdout_fh->get_all_output || ''; is( $stdout, '', 'should be no output to stdout' ); my $html_ref = $f->html; ok( $$html_ref, 'formatter->html exists' ); } { my $f = TAP::Formatter::HTML->new({ silent => 1, output_fh => $output_fh }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); my $stdout = $stdout_fh->get_all_output || ''; is( $stdout, '', 'should be no output to stdout' ); my $html = $output_fh->get_all_output || ''; ok( $html, 'html still output to non-stdout fh when silent is set' ); like( $html, qr|01_pass|, 'html contains file 1' ); my $html_ref = $f->html; ok( $$html_ref, 'formatter->html exists' ); } libtap-formatter-html-perl-0.11+dfsg.orig/t/06_output.t0000444000175000017500000000055312076610727022013 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my @tests = glob( 't/data/*.pl' ); my $f = TAP::Formatter::HTML->new({ silent => 1 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); # TODO: test output to a custom FH libtap-formatter-html-perl-0.11+dfsg.orig/t/20_prove_html.t0000444000175000017500000000327512076610727022632 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use App::Prove; my $tmp = FileTempTFH->new; # prove -P HTML=output:output.html,css_uri:http://www.spurkis.org/style.css,js_uri:jquery.js,js_uri:custom.js,force_inline_css:0,force_inline_js:0 my @args = ( '--norc', '-Q', '-P', join( ',', 'HTML=outfile:' . $tmp->filename, qw( css_uri:http://www.spurkis.org/style.css css_uri:custom.css js_uri:http://www.spurkis.org/jquery.js js_uri:custom.js force_inline_css:0 force_inline_js:0 ), ), 't/data/01_pass.pl', ); my $run; my $app = App::Prove->new; eval { $app->process_args( @args ); $run = $app->run; }; my $e = $@ || ''; ok( $run, 'app->run' ); is( $e, '', '... and no error' ); can_ok( 'App::Prove::Plugin::HTML', 'load' ); can_ok( 'TAP::Formatter::HTML', 'new' ); is( $app->formatter, 'TAP::Formatter::HTML', 'app->formatter' ); is( $ENV{TAP_FORMATTER_HTML_OUTFILE}, $tmp->filename, 'ENV: outfile' ); is( $ENV{TAP_FORMATTER_HTML_CSS_URIS}, 'http://www.spurkis.org/style.css:custom.css', 'ENV: css_uris' ); is( $ENV{TAP_FORMATTER_HTML_JS_URIS}, 'http://www.spurkis.org/jquery.js:custom.js', 'ENV: js_uris' ); is( $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_CSS}, 0, 'ENV: force_inline_css' ); is( $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_JS}, 0, 'ENV: force_inline_js' ); my $out = $tmp->get_all_output || ''; like( $out, qr|\A\s*<.+/html>\s*\Z|ms, 'HTML report output to file' ); like( $out, qr|style.css|, 'css_uri: style.css' ); like( $out, qr|custom.css|, 'css_uri: custom.css' ); like( $out, qr|jquery.js|, 'js_uri: jquery.css' ); like( $out, qr|custom.js|, 'js_uri: custom.css' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/01_basic.t0000444000175000017500000000177512076610727021536 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use File::Basename qw( basename ); use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $stdout_fh = FileTempTFH->new; my $stdout_orig_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) or die "Error opening STDOUT for writing: $!"; STDOUT->fdopen( fileno($stdout_fh), 'w' ) or die "Error redirecting STDOUT: $!"; # Only run 1 test on Windows or tests will hang (RT #81922) my @tests = ($^O =~ /win/i ? 't/data/01_pass.pl' : glob( 't/data/*.pl' )); my $h = TAP::Harness->new({ merge => 1, formatter_class => 'TAP::Formatter::HTML' }); $h->runtests(@tests); STDOUT->fdopen( fileno($stdout_orig_fh), 'w' ) or die "Error resetting STDOUT: $!"; my $stdout = $stdout_fh->get_all_output || ''; isnt( $stdout, '', 'captured test output to stdout' ); foreach my $file (@tests) { my $test = basename( $file ); $test =~ s/\.pl$//; ok( $stdout =~ qr|$test|, "output contains test '$test'" ); } libtap-formatter-html-perl-0.11+dfsg.orig/t/10_win32.t0000444000175000017500000000211612076610727021405 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use URI::file; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); if ($^O !~ /win32/i) { no warnings; $TAP::Formatter::HTML::FAKE_WIN32_URIS = 1; } my $tmp = FileTempTFH->new; my $f = TAP::Formatter::HTML ->new({ silent => 1, css_uris => ['C:\\some\\path', 'file:///C:\\another\\path'], js_uris => ['\\yet\\another\\path', 'file://and/another'], force_inline_css => 0 }) ->output_fh( $tmp ); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); my @tests = ( 't/data/01_pass.pl' ); eval { $h->runtests( @tests ) }; my $e = $@ || ''; is( $e, '', 'no error on generate report with win32 CSS URI' ); is_deeply( $f->css_uris, [ URI::file->new( 'C:\\some\\path', 'win32' ), URI::file->new( 'C:\\another\\path', 'win32' ) ], 'win32 css_uris as expected (RT 37983)' ); is_deeply( $f->js_uris, [ URI::file->new( '\\yet\\another\\path', 'win32' ), URI::file->new( 'file://and/another', 'win32' ) ], 'win32 js_uris as expected (RT 37983)' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/08_env_vars.t0000444000175000017500000000262012076610727022275 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $tmp = FileTempTFH->new; $ENV{TAP_FORMATTER_HTML_OUTFILE} = "$tmp"; $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_CSS} = "0"; $ENV{TAP_FORMATTER_HTML_CSS_URIS} = "/foo/bar.css:/bar/baz.css"; $ENV{TAP_FORMATTER_HTML_JS_URIS} = "/foo/bar.js:/bar/baz.js"; $ENV{TAP_FORMATTER_HTML_TEMPLATE} = "/foo/bar/baz.tt"; my $f = TAP::Formatter::HTML->new({ really_quiet => 1 }); isnt( $f->output_fh, $f->stdout, 'TAP_FORMATTER_HTML_OUTFILE sets output_fh' ); is( $f->force_inline_css, 0, 'TAP_FORMATTER_HTML_FORCE_INLINE_CSS' ); is( $f->template, '/foo/bar/baz.tt', 'TAP_FORMATTER_HTML_TEMPLATE' ); is_deeply( $f->css_uris, [qw( /foo/bar.css /bar/baz.css )], 'TAP_FORMATTER_HTML_CSS_URIS' ); is_deeply( $f->js_uris, [qw( /foo/bar.js /bar/baz.js )], 'TAP_FORMATTER_HTML_JS_URIS' ); # Test #2 - make sure OUTFILE works... delete @ENV{qw(TAP_FORMATTER_HTML_CSS_URIS TAP_FORMATTER_HTML_JS_URIS TAP_FORMATTER_HTML_TEMPLATE)}; my $h = TAP::Harness->new({ merge => 1, verbosity => -3, formatter_class => 'TAP::Formatter::HTML' }); $h->runtests( 't/data/01_pass.pl' ); my $html = $tmp->get_all_output; ok( $html, 'TAP_FORMATTER_HTML_OUTFILE generates file' ); like( $html, qr|01_pass|, 'file contains expected output' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/lib/0000755000175000017500000000000012076610727020526 5ustar salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/t/lib/FileTempTFH.pm0000444000175000017500000000041212076610727023126 0ustar salvisalvipackage FileTempTFH; use strict; use warnings; use Fcntl qw( SEEK_SET ); use base qw( File::Temp ); sub get_all_output { my $self = shift; $self->seek( 0, SEEK_SET ); my $html; { local $/ = undef; $html = <$self>; } return $html; } 1; libtap-formatter-html-perl-0.11+dfsg.orig/t/31_inc_path.t0000444000175000017500000000117712076610727022241 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use TAP::Harness; use TAP::Formatter::HTML; eval { for (1..64) { push @INC, "lib" } #my $t = TAP::Formatter::HTML->default_template_processor; my @tests = 't/data/01_pass.pl'; my $f = TAP::Formatter::HTML->new({ silent => 1 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); }; my $e = $@; unlike($e, qr/INCLUDE_PATH exceeds .+ directories/i, 'RT 74364 - INCLUDE_PATH exceeds num dirs'); ok(!$e, 'no error set when calling default_template_processor with lots of dirs in @INC') || diag($e); libtap-formatter-html-perl-0.11+dfsg.orig/t/11_force_inline.t0000444000175000017500000000156412076610727023106 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use TAP::Parser::Aggregator; use_ok( 'TAP::Formatter::HTML' ); my @tests = ( 't/data/01_pass.pl' ); my $tmp = FileTempTFH->new; my $f = TAP::Formatter::HTML->new({ silent => 1 })->output_fh( $tmp )->force_inline_css(1)->force_inline_js(1); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); my $html = $tmp->get_all_output; ok( $html =~ qr|01_pass|, 'html contains file 1' ); ok( $html =~ qr|jQuery JavaScript Library v\d+.\d+.\d+|, 'html contains jQuery src' ); ok( $html =~ qr|default javascript for report|, 'html contains default js' ); ok( $html =~ qr|default stylesheet for report body|, 'html contains default css body' ); ok( $html =~ qr|default stylesheet for report page layout|, 'html contains default css page' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/09_empty_testdir.t0000444000175000017500000000066512076610727023356 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $tmp = FileTempTFH->new; my $f = TAP::Formatter::HTML->new({ silent => 1 })->output_fh( $tmp )->force_inline_css(0); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); eval { $h->runtests( ) }; my $e = $@ || ''; is( $e, '', 'no error on empty test dir (RT 41411)' ); libtap-formatter-html-perl-0.11+dfsg.orig/t/05_quiet.t0000444000175000017500000000164012076610727021577 0ustar salvisalviuse strict; use warnings; use lib 'lib'; use lib 't/lib'; use Test::More 'no_plan'; use FileTempTFH; use TAP::Harness; use_ok( 'TAP::Formatter::HTML' ); my $stdout_fh = FileTempTFH->new; my $stdout_orig_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) or die "Error opening STDOUT for writing: $!"; STDOUT->fdopen( fileno($stdout_fh), 'w' ) or die "Error re-directing STDOUT: $!"; my @tests = ( 't/data/01_pass.pl', 't/data/02_fail.pl' ); my $f = TAP::Formatter::HTML->new({ escape_output => 1, quiet => 1, force_inline_css => 0 }); my $h = TAP::Harness->new({ merge => 1, formatter => $f }); $h->runtests(@tests); STDOUT->fdopen( fileno($stdout_orig_fh), 'w' ) or die "Error resetting STDOUT: $!"; my $stdout = $stdout_fh->get_all_output || ''; like( $stdout, qr|\A(?!\s*\Z|ms, 'HTML report should be output last' ); libtap-formatter-html-perl-0.11+dfsg.orig/MANIFEST0000444000175000017500000000173112076716223020644 0ustar salvisalviBuild.PL Changes examples/DBD-SQLite-example.html examples/test-output.html lib/App/Prove/Plugin/HTML.pm lib/TAP/Formatter/HTML.pm lib/TAP/Formatter/HTML/default_page.css lib/TAP/Formatter/HTML/default_report.css lib/TAP/Formatter/HTML/default_report.js lib/TAP/Formatter/HTML/default_report.tt2 lib/TAP/Formatter/HTML/Session.pm Makefile.PL MANIFEST This list of files META.json META.yml README t/01_basic.t t/02_escape_output.t t/03_silent.t t/04_really_quiet.t t/05_quiet.t t/06_output.t t/07_multiple_aggregate.t t/08_env_vars.t t/09_empty_testdir.t t/10_win32.t t/11_force_inline.t t/20_prove_html.t t/30_tap_harness_compat.t t/31_inc_path.t t/99_test_pod.t t/data/01_pass.pl t/data/02_fail.pl t/data/03_plan_fail.pl t/data/04_die_fail.pl t/data/05_compile_fail.pl t/data/06_skip_all.pl t/data/07_todo_pass.pl t/data/08_html_in_output.pl t/data/09_skip_error.pl t/data/10_todo_skip.pl t/data/11_lots_of_tests.pl t/lib/FileTempTFH.pm t/selenium/server.pl t/selenium_basic.t Todo libtap-formatter-html-perl-0.11+dfsg.orig/Makefile.PL0000444000175000017500000000230512076610727021465 0ustar salvisalvi# Note: this file was auto-generated by Module::Build::Compat version 0.3800 require 5.006000; unless (eval "use Module::Build::Compat 0.02; 1" ) { print "This module requires Module::Build to install itself.\n"; require ExtUtils::MakeMaker; my $yn = ExtUtils::MakeMaker::prompt (' Install Module::Build now from CPAN?', 'y'); unless ($yn =~ /^y/i) { die " *** Cannot install without Module::Build. Exiting ...\n"; } require Cwd; require File::Spec; require CPAN; # Save this 'cause CPAN will chdir all over the place. my $cwd = Cwd::cwd(); CPAN::Shell->install('Module::Build::Compat'); CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate or die "Couldn't install Module::Build, giving up.\n"; chdir $cwd or die "Cannot chdir() back to $cwd: $!"; } eval "use Module::Build::Compat 0.02; 1" or die $@; Module::Build::Compat->run_build_pl(args => \@ARGV); my $build_script = 'Build'; $build_script .= '.com' if $^O eq 'VMS'; exit(0) unless(-e $build_script); # cpantesters convention require Module::Build; Module::Build::Compat->write_makefile(build_class => 'Module::Build'); libtap-formatter-html-perl-0.11+dfsg.orig/Todo0000444000175000017500000000210412076610727020340 0ustar salvisalviMore tests! * parse the generated output * check the view given to the TT view Reports from Nadim Khemir: * integrate into build scripts (eg: M::B) * possible to open the test file and show the test itself? * why the need to stop using Test::Harness? Various bug reports (+ Patch!) by Hemingway: * https://rt.cpan.org/Ticket/Display.html?id=41457 Progress console: * https://rt.cpan.org/Ticket/Display.html?id=40627 Script still running bug * when you navigate away from page * only on big test outputs * jquery cleanup? Sometimes test details don't collapse properly! * doesn't happen in FireFox 3? * related to the scrollTo? * could hide & show the tr after the slideToggle? sort by cols * time! * test file * percent support file output - in progress * prove --html=output.html * allow output to STDOUT * write an App::Prove plugin wrap unknown test output's in

expand all tests
expand failed tests

collapse current test (from halway down big tests, maybe a mouseover file or something)

Give the test suite a title...

libtap-formatter-html-perl-0.11+dfsg.orig/lib/0000755000175000017500000000000012076610727020263 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/App/0000755000175000017500000000000012076610727021003 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/App/Prove/0000755000175000017500000000000012076610727022076 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/App/Prove/Plugin/0000755000175000017500000000000012076610727023334 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/App/Prove/Plugin/HTML.pm0000444000175000017500000000612412076610727024437 0ustar  salvisalvipackage App::Prove::Plugin::HTML;

=head1 NAME

App::Prove::Plugin::HTML - a prove plugin for HTML output

=head1 SYNOPSIS

 # command-line usage:
 prove -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0

 # NOTE: this is currently in alpha, this usage will likely change!

=cut

use strict;
use warnings;

use TAP::Formatter::HTML;

our $VERSION = '0.11';

sub import {
    my ($class, @args) = @_;
    # deprecated, do nothing
    return $class;
}

sub load {
    my ($class, $p) = @_;
    my @args = @{ $p->{args} };
    my $app  = $p->{app_prove};

    # parse the args
    my %TFH_args;
    foreach my $arg (@args) {
	my ($key, $val) = split(/:/, $arg, 2);
	if (grep {$key eq $_} qw(css_uri js_uri)) {
	    push @{ $TFH_args{$key . 's'}}, $val;
	} else {
	    $TFH_args{$key} = $val;
	}
    }

    # set the formatter to use
    $app->formatter( 'TAP::Formatter::HTML' );

    # set ENV vars in order to pass args to TAP::Formatter::HTML
    # horrible, but it's currently the only way :-/
    while (my ($key, $val) = each %TFH_args) {
	$val = join( ':', @$val ) if (ref($val) eq 'ARRAY');
	$ENV{"TAP_FORMATTER_HTML_".uc($key)} = $val;
    }

    # we're done
    return $class;
}


1;

__END__

=head1 DESCRIPTION

This is a quick & dirty second attempt at making L easier
to use from the command line.  It will change once L has better
support for plugins than need to take cmdline data.

The original goal was to be able to specify all the args on the cmdline, ala:

  prove --html=output.html --css-uri foo.css --css-uri bar.css --force-inline-css 0

But this is currently not possible with the way the L plugin system
works.

As a compromise, you must use the following syntax:

  prove -P HTML=arg1:val1,arg2:val2,...

Where I is any L parameter that is configurable via
C<%ENV>.

=head2 Example

  prove -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0

This will cause L to load this plugin, which loads L
for you, and sets I to C to save you some typing.

To configure L, the following C<%ENV> vars are set:

  TAP_FORMATTER_HTML_OUTFILE=out.html
  TAP_FORMATTER_HTML_FORCE_INLINE_CSS=0
  TAP_FORMATTER_HTML_CSS_URIS=style.css
  TAP_FORMATTER_HTML_JS_URIS=func.js

Yes, you can pass 2 or more I or I args.

=head2 %ENV vars?!

Briefly, L currently only lets you specify the C for
L, it doesn't let you instantiate a formatter, or pass config to
the formatter.

I  If it bugs you too,
then join the L devs and help us fix it ;-).

=head1 BUGS

Please use http://rt.cpan.org to report any issues.

=head1 AUTHOR

Steve Purkis 

=head1 COPYRIGHT

Copyright (c) 2008-2010 Steve Purkis , S Purkis Consulting Ltd.
All rights reserved.

This module is released under the same terms as Perl itself.

=head1 SEE ALSO

L, L, L

=cut
libtap-formatter-html-perl-0.11+dfsg.orig/lib/TAP/0000755000175000017500000000000012076610727020707 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/TAP/Formatter/0000755000175000017500000000000012076610727022652 5ustar  salvisalvilibtap-formatter-html-perl-0.11+dfsg.orig/lib/TAP/Formatter/HTML.pm0000444000175000017500000006004112076610727023753 0ustar  salvisalvi=head1 NAME

TAP::Formatter::HTML - TAP Test Harness output delegate for html output

=head1 SYNOPSIS

 ##
 ## command-line usage (alpha):
 ##
 prove -m -Q -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0

 # backwards compat usage:
 prove -m -Q --formatter=TAP::Formatter::HTML >output.html

 # for more detail:
 perldoc App::Prove::Plugin::HTML

 ##
 ## perl usage:
 ##
 use TAP::Harness;

 my @tests = glob( 't/*.t' );
 my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML',
                                   merge => 1 });
 $harness->runtests( @tests );
 # prints HTML to STDOUT by default

 # or if you really don't want STDERR merged in:
 my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML' });

 # to use a custom formatter:
 my $fmt = TAP::Formatter::HTML->new;
 $fmt->css_uris([])->inline_css( $my_css )
     ->js_uris(['http://mysite.com/jquery.js', 'http://mysite.com/custom.js'])
     ->inline_js( '$(div.summary).hide()' );

 my $harness = TAP::Harness->new({ formatter => $fmt, merge => 1 });

 # to output HTML to a file[handle]:
 $fmt->output_fh( $fh );
 $fmt->output_file( '/tmp/foo.html' );

 # you can use your own customized templates too:
 $fmt->template('custom.tt2')
     ->template_processor( Template->new )
     ->force_inline_css(0)
     ->force_inline_js(0);

=cut

package TAP::Formatter::HTML;

use strict;
use warnings;

use URI;
use URI::file;
use Template;
use POSIX qw( ceil );
use IO::File;
use File::Temp qw( tempfile tempdir );
use File::Spec::Functions qw( catdir catfile file_name_is_absolute rel2abs );

use TAP::Formatter::HTML::Session;

# DEBUG:
#use Data::Dumper 'Dumper';

use base qw( TAP::Base );
use accessors qw( verbosity stdout output_fh escape_output tests session_class sessions
		  template_processor template html html_id_iterator minify color
		  css_uris js_uris inline_css inline_js abs_file_paths force_inline_css force_inline_js );

use constant default_session_class => 'TAP::Formatter::HTML::Session';
use constant default_template      => 'TAP/Formatter/HTML/default_report.tt2';
use constant default_js_uris       => ['file:TAP/Formatter/HTML/jquery-1.4.2.min.js',
				       'file:TAP/Formatter/HTML/jquery.tablesorter-2.0.3.min.js',
				       'file:TAP/Formatter/HTML/default_report.js'];
use constant default_css_uris      => ['file:TAP/Formatter/HTML/default_page.css',
				       'file:TAP/Formatter/HTML/default_report.css'];

use constant severity_map => {
			      ''          => 0,
			      'very-low'  => 1,
			      'low'       => 2,
			      'med'       => 3,
			      'high'      => 4,
			      'very-high' => 5,
			      0 => '',
			      1 => 'very-low',
			      2 => 'low',
			      3 => 'med',
			      4 => 'high',
			      5 => 'very-high',
			     };

our $VERSION = '0.11';
our $FAKE_WIN32_URIS = 0; # for testing only

sub _initialize {
    my ($self, $args) = @_;

    $args ||= {};
    $self->SUPER::_initialize($args);

    my $stdout_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' )
      or die "Error opening STDOUT for writing: $!";

    $self->verbosity( 0 )
         ->stdout( $stdout_fh )
         ->output_fh( $stdout_fh )
	 ->minify( 1 )
	 ->escape_output( 0 )
         ->abs_file_paths( 1 )
         ->abs_file_paths( 1 )
         ->force_inline_css( 1 )
         ->force_inline_js( 0 )
         ->session_class( $self->default_session_class )
         ->template_processor( $self->default_template_processor )
         ->template( $self->default_template )
         ->js_uris( $self->default_js_uris )
         ->css_uris( $self->default_css_uris )
         ->inline_js( '' )
	 ->inline_css( '' )
	 ->sessions( [] );

    $self->check_for_overrides_in_env;

    # Laziness...
    # trust the user knows what they're doing with the args:
    foreach my $key (keys %$args) {
	$self->$key( $args->{$key} ) if ($self->can( $key ));
    }

    $self->html_id_iterator( $self->create_iterator( $args ) );

    return $self;
}

sub check_for_overrides_in_env {
    my $self = shift;

    if (my $file = $ENV{TAP_FORMATTER_HTML_OUTFILE}) {
	$self->output_file( $file );
    }

    my $force_css = $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_CSS};
    if (defined( $force_css )) {
	$self->force_inline_css( $force_css );
    }

    my $force_js = $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_JS};
    if (defined( $force_js )) {
	$self->force_inline_js( $force_js );
    }

    if (my $uris = $ENV{TAP_FORMATTER_HTML_CSS_URIS}) {
	my $list = [ split( ':', $uris ) ];
	$self->css_uris( $list );
    }

    if (my $uris = $ENV{TAP_FORMATTER_HTML_JS_URIS}) {
	my $list = [ split( ':', $uris ) ];
	$self->js_uris( $list );
    }

    if (my $file = $ENV{TAP_FORMATTER_HTML_TEMPLATE}) {
	$self->template( $file );
    }

    return $self;
}

sub default_template_processor {
    my $path = __FILE__;
    $path =~ s/.TAP.Formatter.HTML.pm$//;
    return Template->new(
        # arguably shouldn't compile as this is only used once
        COMPILE_DIR  => catdir( tempdir( CLEANUP => 1 ), 'TAP-Formatter-HTML' ),
        COMPILE_EXT  => '.ttc',
        INCLUDE_PATH => $path,
    );
}


sub output_file {
    my ($self, $file) = @_;
    my $fh = IO::File->new( $file, 'w' )
      or die "Error opening '$file' for writing: $!";
    $self->output_fh( $fh );
}

sub create_iterator {
    my $self = shift;
    my $args = shift || {};
    my $prefix = $args->{html_id_prefix} || 't';
    my $i = 0;
    my $iter = sub { return $prefix . $i++ };
}

sub verbose {
    my $self = shift;
    # emulate a classic accessor for compat w/TAP::Formatter::Console:
    if (@_) { $self->verbosity(1) }
    return $self->verbosity >= 1;
}

sub quiet {
    my $self = shift;
    # emulate a classic accessor for compat w/TAP::Formatter::Console:
    if (@_) { $self->verbosity(-1) }
    return $self->verbosity <= -1;
}

sub really_quiet {
    my $self = shift;
    # emulate a classic accessor for compat w/TAP::Formatter::Console:
    if (@_) { $self->verbosity(-2) }
    return $self->verbosity <= -2;
}

sub silent {
    my $self = shift;
    # emulate a classic accessor for compat w/TAP::Formatter::Console:
    if (@_) { $self->verbosity(-3) }
    return $self->verbosity <= -3;
}

# Called by Test::Harness before any test output is generated.
sub prepare {
    my ($self, @tests) = @_;
    # warn ref($self) . "->prepare called with args:\n" . Dumper( \@tests );
    $self->info( 'running ', scalar @tests, ' tests' );
    $self->tests( [@tests] );
}

# Called to create a new test session. A test session looks like this:
#
#    my $session = $formatter->open_test( $test, $parser );
#    while ( defined( my $result = $parser->next ) ) {
#        $session->result($result);
#        exit 1 if $result->is_bailout;
#    }
#    $session->close_test;
sub open_test {
    my ($self, $test, $parser) = @_;
    #warn ref($self) . "->open_test called with args: " . Dumper( [$test, $parser] );
    my $session = $self->session_class->new({ test => $test,
					      parser => $parser,
					      formatter => $self });
    push @{ $self->sessions }, $session;
    return $session;
}

# $str = $harness->summary( $aggregate );
#
# C produces the summary report after all tests are run.  The argument is
# an aggregate.
sub summary {
    my ($self, $aggregate) = @_;
    #warn ref($self) . "->summary called with args: " . Dumper( [$aggregate] );

    # farmed out to make sub-classing easy:
    my $report = $self->prepare_report( $aggregate );
    $self->generate_report( $report );

    # if silent is set, only print HTML if we're not printing to stdout
    if (! $self->silent or $self->output_fh->fileno != fileno(STDOUT)) {
	print { $self->output_fh } ${ $self->html };
	$self->output_fh->flush;
    }

    return $self;
}

sub generate_report {
    my ($self, $r) = @_;

    $self->check_uris;
    $self->slurp_css if $self->force_inline_css;
    $self->slurp_js if $self->force_inline_js;

    my $params = {
		  report => $r,
		  js_uris  => $self->js_uris,
		  css_uris => $self->css_uris,
		  inline_js  => $self->inline_js,
		  inline_css => $self->inline_css,
		  formatter => { class => ref( $self ),
				 version => $self->VERSION },
		 };

    my $html = '';
    $self->template_processor->process( $self->template, $params, \$html )
      || die $self->template_processor->error;

    $self->html( \$html );
    $self->minify_report if $self->minify;

    return $self;
}

# try and reduce the size of the report
sub minify_report {
    my $self = shift;
    my $html_ref = $self->html;
    $$html_ref =~ s/^\t+//mg;
    return $self;
}

# convert all uris to URI objs
# check file uris (if relative & not found, try & find them in @INC)
sub check_uris {
    my ($self) = @_;

    foreach my $uri_list ($self->js_uris, $self->css_uris) {
	# take them out of the list to verify, push them back on later
	my @uris = splice( @$uri_list, 0, scalar @$uri_list );
	foreach my $uri (@uris) {
	    if (($^O =~ /win32/i or $FAKE_WIN32_URIS)
		and $uri =~ /^(?:(?:file)|(?:\w:)?\\)/) {
		$uri = URI::file->new($uri, 'win32');
	    } else {
	        $uri = URI->new( $uri );
    	    }
	    if ($uri->scheme && $uri->scheme eq 'file') {
		my $path = $uri->path;
		unless (file_name_is_absolute($path)) {
		    my $new_path;
		    if (-e $path) {
			$new_path = rel2abs( $path ) if ($self->abs_file_paths);
		    } else {
			$new_path = $self->find_in_INC( $path );
		    }
                    if ($new_path) {
                        if (($^O =~ /win32/i or $FAKE_WIN32_URIS)) {
                            $uri = URI::file->new("file://$new_path", 'win32');
                        } else {
                            $uri->path( $new_path );
                        }
                    }
		}
	    }
	    push @$uri_list, $uri;
	}
    }

    return $self;
}

sub prepare_report {
    my ($self, $a) = @_;

    my $r = {
	     tests => [],
	     start_time => '?',
	     end_time => '?',
	     elapsed_time => $a->elapsed_timestr,
	    };


    # add aggregate test info:
    for my $key (qw(
		    total
		    has_errors
		    has_problems
		    failed
		    parse_errors
		    passed
		    skipped
		    todo
		    todo_passed
		    wait
		    exit
		   )) {
	$r->{$key} = $a->$key;
    }

    # do some other handy calcs:
    $r->{actual_passed} = $r->{passed} + $r->{todo_passed};
    if ($r->{total}) {
	$r->{percent_passed} = sprintf('%.1f', $r->{actual_passed} / $r->{total} * 100);
    } else {
	$r->{percent_passed} = 0;
    }

    # estimate # files (# sessions could be different?):
    $r->{num_files} = scalar @{ $self->sessions };

    # add test results:
    my $total_time = 0;
    foreach my $s (@{ $self->sessions }) {
	my $sr = $s->as_report;
	push @{$r->{tests}}, $sr;
	$total_time += $sr->{elapsed_time} || 0;
    }
    $r->{total_time} = $total_time;

    # estimate total severity:
    my $smap = $self->severity_map;
    my $severity = 0;
    $severity += $smap->{$_->{severity} || ''} for @{$r->{tests}};
    my $avg_severity = 0;
    if (scalar @{$r->{tests}}) {
	$avg_severity = ceil($severity / scalar( @{$r->{tests}} ));
    }
    $r->{severity} = $smap->{$avg_severity};

    # TODO: coverage?

    return $r;
}

# adapted from Test::TAP::HTMLMatrix
# always return abs file paths if $self->abs_file_paths is on
sub find_in_INC {
    my ($self, $file) = @_;

    foreach my $path (grep { not ref } @INC) {
	my $target = catfile($path, $file);
	if (-e $target) {
	    $target = rel2abs($target) if $self->abs_file_paths;
	    return $target;
	}
    }

    # non-fatal
    $self->log("Warning: couldn't find $file in \@INC");
    return;
}

# adapted from Test::TAP::HTMLMatrix
# slurp all 'file' uris, if possible
# note: doesn't remove them from the css_uris list, just in case...
sub slurp_css {
    my ($self) = shift;
    $self->info("slurping css files inline");

    my $inline_css = '';
    $self->_slurp_uris( $self->css_uris, \$inline_css );

    # append any inline css so it gets interpreted last:
    $inline_css .= "\n" . $self->inline_css if $self->inline_css;

    $self->inline_css( $inline_css );
}

sub slurp_js {
    my ($self) = shift;
    $self->info("slurping js files inline");

    my $inline_js = '';
    $self->_slurp_uris( $self->js_uris, \$inline_js );

    # append any inline js so it gets interpreted last:
    $inline_js .= "\n" . $self->inline_js if $self->inline_js;

    $self->inline_js( $inline_js );
}

sub _slurp_uris {
    my ($self, $uris, $slurp_to_ref) = @_;

    foreach my $uri (@$uris) {
	my $scheme = $uri->scheme;
	if ($scheme && $scheme eq 'file') {
	    my $path = $uri->path;
	    if (-e $path) {
		if (open my $fh, $path) {
		    local $/ = undef;
		    $$slurp_to_ref .= <$fh>;
		    $$slurp_to_ref .= "\n";
		} else {
		    $self->log("Warning: couldn't open $path: $!");
		}
	    } else {
		$self->log("Warning: couldn't read $path: file does not exist!");
	    }
	} else {
	    $self->log("Warning: can't include $uri inline: not a file uri");
	}
    }

    return $slurp_to_ref;
}



sub log {
    my $self = shift;
    push @_, "\n" unless grep {/\n/} @_;
    $self->_output( @_ );
    return $self;
}

sub info {
    my $self = shift;
    return unless $self->verbose;
    return $self->log( @_ );
}

sub log_test {
    my $self = shift;
    return if $self->really_quiet;
    return $self->log( @_ );
}

sub log_test_info {
    my $self = shift;
    return if $self->quiet;
    return $self->log( @_ );
}

sub _output {
    my $self = shift;
    return if $self->silent;
    if (ref($_[0]) && ref( $_[0]) eq 'SCALAR') {
	# DEPRECATED: printing HTML:
	print { $self->stdout } ${ $_[0] };
    } else {
	unshift @_, '# ' if $self->escape_output;
	print { $self->stdout } @_;
    }
}


1;


__END__

=head1 DESCRIPTION

This module provides HTML output formatting for L (a replacement
for L.  It is largely based on ideas from
L (which was built on L and thus had a
few limitations - hence this module).  For sample output, see:

L

This module is targeted at all users of automated test suites.  It's meant to
make reading test results easier, giving you a visual summary of your test suite
and letting you drill down into individual failures (which will hopefully make
testing more likely to happen at your organization ;-).

The design goals are:

=over 4

=item *

I

Once you've got your test report, it should be obvious how to use it.

=item *

I

It should be helpful by pointing out I & I your test suite is
breaking.  If you've written your tests well, it should give you enough info to
start tracking down the issue.

=item *

I

Eg: should be a clean install from CPAN, and you shouldn't need to modify your
existing test suite to get up & running, though I unfortunately>.

=item *

I

You shouldn't need to do any custom-coding to get it working - the default
configuration & templates should be enough to get started with.  Once installed
it should be a matter of running:

 % prove -m -Q --formatter=TAP::Formatter::HTML >output.html

From your project's home dir, and opening the resulting file.

=item *

I

You should be able to configure & customize it to suit your needs.  As such,
css, javascript and templates are all configurable.

=back

=head1 METHODS

=head2 CONSTRUCTOR

=head3 new

  my $fmt = $class->new({ %args });

=head2 ACCESSORS

All chaining L:

=head3 verbosity

  $fmt->verbosity( [ $v ] )

Verbosity level, as defined in L:

     1   verbose        Print individual test results (and more) to STDOUT.
     0   normal
    -1   quiet          Suppress some test output (eg: test failures).
    -2   really quiet   Suppress everything to STDOUT but the HTML report.
    -3   silent         Suppress all output to STDOUT, including the HTML report.

Note that the report is also available via L.  You can also provide a
custom L (aka L) that will be used instead of
L, even if I is on.

=head3 stdout

  $fmt->stdout( [ \*FH ] );

An L filehandle for catching standard output.  Defaults to C.

=head3 output_fh

  $fmt->output_fh( [ \*FH ] );

An L filehandle for printing the HTML report to.  Defaults to the
same object as L.

B If L is set to C, printing to C will
still occur.  (that is, assuming you've opened a different file, B
C).

=head3 output_file

  $fmt->output_file( $file_name )

Not strictly an accessor - this is a shortcut for setting L,
equivalent to:

  $fmt->output_fh( IO::File->new( $file_name, 'w' ) );

You can set this with the C
environment variable

=head3 escape_output

  $fmt->escape_output( [ $boolean ] );

If set, all output to L is escaped.  This is probably only useful
if you're testing the formatter.
Defaults to C<0>.

=head3 html

  $fmt->html( [ \$html ] );

This is a reference to the scalar containing the html generated on the last
test run.  Useful if you have L set to C, and have not
provided a custom L to write the report to.

=head3 tests

  $fmt->tests( [ \@test_files ] )

A list of test files we're running, set by L.

=head3 session_class

  $fmt->session_class( [ $class ] )

Class to use for L test sessions.  You probably won't need to use
this unless you're hacking or sub-classing the formatter.
Defaults to L.

=head3 sessions

  $fmt->sessions( [ \@sessions ] )

Test sessions added by L.  You probably won't need to use this
unless you're hacking or sub-classing the formatter.

=head3 template_processor

  $fmt->template_processor( [ $processor ] )

The template processor to use.
Defaults to a TT2 L