Tag old version. Update trunk to new version with additional tests v0.04
Tomas Doran [Sun, 28 Sep 2008 15:47:17 +0000 (15:47 +0000)]
13 files changed:
Changes
MANIFEST [new file with mode: 0644]
MANIFEST.SKIP
Makefile.PL
README
lib/Catalyst/Authentication/Credential/HTTP/Proxy.pm [new file with mode: 0644]
lib/Catalyst/Authentication/Credential/HTTP/Proxy/User.pm [copied from lib/Catalyst/Plugin/Authentication/Credential/HTTP/User.pm with 68% similarity]
lib/Catalyst/Authentication/Credential/HTTP/User.pm [moved from lib/Catalyst/Plugin/Authentication/Credential/HTTP/User.pm with 100% similarity]
lib/Catalyst/Plugin/Authentication/Credential/HTTP/Proxy.pm [deleted file]
t/kwalitee.t [new file with mode: 0755]
t/live_app.t [new file with mode: 0644]
t/mock.t [new file with mode: 0644]
t/use.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 7fdab99..a6dc9fd 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,3 +1,8 @@
+0.04   2008-09-25
+        - Change namespace to remove ::Plugin:: for new auth framework.
+        - Gutted most of the code in the module by subclassing 
+          Catalyst::Authentication::Credential::HTTP.
+
 0.03    2007-07-18
         - Fix broken test
 
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..e78ced9
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,24 @@
+Changes
+inc/Module/AutoInstall.pm
+inc/Module/Install.pm
+inc/Module/Install/AutoInstall.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Include.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/Catalyst/Authentication/Credential/HTTP/Proxy.pm
+lib/Catalyst/Authentication/Credential/HTTP/Proxy/User.pm
+Makefile.PL
+MANIFEST                       This list of files
+META.yml
+README
+t/kwalitee.t
+t/live_app.t
+t/mock.t
+t/pod.t
+t/pod_coverage.t
+t/use.t
index f21a21f..dfded08 100644 (file)
@@ -27,3 +27,6 @@
 
 # No tarballs!
 \.gz$
+
+# No shipt conf please.
+\.shipit
\ No newline at end of file
index 19455ff..905b2a4 100644 (file)
@@ -1,12 +1,14 @@
 use inc::Module::Install 0.65;
 
-name 'Catalyst-Plugin-Authentication-Credential-HTTP-Proxy';
-all_from 'lib/Catalyst/Plugin/Authentication/Credential/HTTP/Proxy.pm';
+name 'Catalyst-Authentication-Credential-HTTP-Proxy';
+all_from 'lib/Catalyst/Authentication/Credential/HTTP/Proxy.pm';
 
 requires 'Catalyst::Runtime';
 requires 'Catalyst::Plugin::Authentication';
-requires 'Test::MockObject';
+requires 'Catalyst::Authentication::Credential::HTTP' => '1.005';
 requires 'LWP::Simple';
+build_requires 'Test::MockObject';
+build_requires 'Test::Exception';
 
 auto_install;
 WriteAll;
diff --git a/README b/README
index 3410e67..0734b3a 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 NAME
-    Catalyst::Plugin::Authentication::Credential::HTTP::Proxy - HTTP Proxy
+    Catalyst::Authentication::Credential::HTTP::Proxy - HTTP Proxy
     authentication for Catlayst.
 
 SYNOPSIS
@@ -68,10 +68,12 @@ METHODS
         header to demand authentication data from the user agent.
 
 AUTHORS
-    Marcus Ramberg <mramberg@cpan.org
+    Marcus Ramberg <mramberg@cpan.org>
+    
+    Tomas Doran <bobtfish@bobtfish.net>
 
 COPYRIGHT & LICENSE
-            Copyright (c) 2005 the aforementioned authors. All rights
+            Copyright (c) 2005-2008 the aforementioned authors. All rights
             reserved. This program is free software; you can redistribute
             it and/or modify it under the same terms as Perl itself.
 
diff --git a/lib/Catalyst/Authentication/Credential/HTTP/Proxy.pm b/lib/Catalyst/Authentication/Credential/HTTP/Proxy.pm
new file mode 100644 (file)
index 0000000..6b16f0e
--- /dev/null
@@ -0,0 +1,159 @@
+package Catalyst::Authentication::Credential::HTTP::Proxy;
+use base qw/Catalyst::Authentication::Credential::HTTP/;
+
+use strict;
+use warnings;
+
+use String::Escape ();
+use URI::Escape    ();
+use Catalyst::Authentication::Credential::HTTP::Proxy::User;
+
+our $VERSION = "0.04";
+
+sub init {
+    my ($self) = @_;
+    
+    my $type = $self->_config->{'type'} ||= 'basic';
+    
+    if (!$self->_config->{url}) {
+        Catalyst::Exception->throw(__PACKAGE__ . " configuration does not include a 'url' key, cannot proceed");
+    }
+    
+    if (!grep /^$type$/, ('basic')) {
+        Catalyst::Exception->throw(__PACKAGE__ . " used with unsupported authentication type: " . $type);
+    }
+}
+
+sub authenticate_basic {
+    my ( $self, $c, $realm, $auth_info ) = @_;
+
+    $c->log->debug('Checking http basic authentication.') if $c->debug;
+
+    my $headers = $c->req->headers;
+
+    if ( my ( $user, $password ) = $headers->authorization_basic ) {
+        my $ua = Catalyst::Authentication::Credential::HTTP::Proxy::User->new;
+        $ua->credentials($user, $password);
+        my $resp = $ua->get($self->_config->{url});
+        if ( $resp->is_success ) {
+            # Config username_field TODO
+               my $user_obj = $realm->find_user( { username => $user }, $c);
+               unless ($user_obj) {
+                $c->log->debug("User '$user' doesn't exist in the default store")
+                    if $c->debug;
+                return;
+            }
+            $c->set_authenticated($user_obj);
+            return 1;
+        }
+        else {
+            $c->log->info('Remote authentication failed:'.$resp->message);
+            return 0;
+        }
+    } 
+    elsif ( $c->debug ) {
+        $c->log->info('No credentials provided for basic auth');
+        return 0;
+    }
+}
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Catalyst::Authentication::Credential::HTTP::Proxy - HTTP Proxy authentication
+for Catlayst.
+
+=head1 SYNOPSIS
+
+    use Catalyst qw/
+        Authentication
+    /;
+
+    $c->config( authentication => {
+        realms => {
+            example => {
+                credential => {
+                    class => 'HTTP::Proxy',
+                    type => 'basic', # Only basic supported
+                    url => 'http://elkland.no/auth',
+                },
+            },
+            store => {
+                class => 'Minimal',
+                users => {
+                    Mufasa => { password => "Circle Of Life", },
+                },
+            },
+        },
+    });
+    
+    sub foo : Local { 
+        my ( $self, $c ) = @_;
+
+        $c->authenticate(); 
+        
+        # either user gets authenticated or 401 is sent
+
+        do_stuff();
+    }
+
+=head1 DESCRIPTION
+
+This moduule lets you use HTTP Proxy authentication with
+L<Catalyst::Plugin::Authentication>.
+
+Currently this module only supports the Basic scheme, but upon request Digest
+will also be added. Patches welcome!
+
+=head1 CONFIG
+
+All configuration is stored in C<< YourApp->config(authentication => { yourrealm => { credential => { class => 'HTTP::Proxy', %config } } } >>.
+
+This should be a hash, and it can contain the following entries:
+
+=over 4
+
+=item url
+
+Required. A url protected with basic authentication to authenticate against.
+
+=item type
+
+Must be either C<basic> or not present (then it defaults to C<basic>).
+
+This will be used to support digest authentication in future.
+
+=back
+
+=head1 METHODS
+
+=over
+
+=item init
+
+Initializes the configuration.
+
+=item authenticate_basic
+
+Looks inside C<< $c->request->headers >> and processes the basic (badly named)
+authorization header. Then authenticates this against the provided url.
+
+=back
+
+=head1 AUTHORS
+
+Marcus Ramberg <mramberg@cpan.org>
+
+Tomas Doran <bobtfish@bobtfish.net>
+
+=head1 COPYRIGHT & LICENSE
+
+        Copyright (c) 2005-2008 the aforementioned authors. All rights
+        reserved. This program is free software; you can redistribute
+        it and/or modify it under the same terms as Perl itself.
+
+=cut
+
@@ -1,4 +1,4 @@
-package Catalyst::Plugin::Authentication::Credential::HTTP::User;
+package Catalyst::Authentication::Credential::HTTP::Proxy::User;
 
 use strict;
 use warnings;
@@ -19,7 +19,7 @@ sub get_basic_credentials {
 
 =head1 NAME
 
-Catalyst::Plugin::Authentication::Credential::HTTP::User - Wrapper for LWP::UserAgent
+Catalyst::Authentication::Credential::HTTP::Proxy::User - Wrapper for LWP::UserAgent
 
 =head1 DESCRIPTION
 
@@ -37,11 +37,11 @@ Returns the set credentials, takes no options.
 
 =head1 AUTHOR
 
-Marcus Ramberg <mramberg@cpan.org
+Marcus Ramberg <mramberg@cpan.org>
 
 =head1 LICENSE
 
-This software is licensed under the same terms as perl itself.i
+This software is licensed under the same terms as perl itself.
 
 =cut
 
diff --git a/lib/Catalyst/Plugin/Authentication/Credential/HTTP/Proxy.pm b/lib/Catalyst/Plugin/Authentication/Credential/HTTP/Proxy.pm
deleted file mode 100644 (file)
index e7afe45..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-package Catalyst::Plugin::Authentication::Credential::HTTP::Proxy;
-use base qw/Catalyst::Plugin::Authentication::Credential::Password/;
-
-use strict;
-use warnings;
-
-use String::Escape ();
-use URI::Escape    ();
-use Catalyst       ();
-use Catalyst::Plugin::Authentication::Credential::HTTP::User;
-use Carp qw/croak/;
-
-our $VERSION = "0.03";
-
-sub authenticate_http_proxy {
-    my $c = shift;
-
-    my $headers = $c->req->headers;
-
-    croak "url setting required for authentication" 
-        unless $c->config->{authentication}{http_proxy}{url};
-    if ( my ( $user, $password ) = $headers->authorization_basic ) {
-
-        my $ua=Catalyst::Plugin::Authentication::Credential::HTTP::User->new;
-        $ua->credentials($user,$password);
-        my $resp= $ua->get($c->config->{authentication}{http_proxy}{url});
-        if ( $resp->is_success ) {
-            if ( my $store = $c->config->{authentication}{http_proxy}{store} ) {
-                $user = $store->get_user($user);
-            } elsif ( my $user_obj = $c->get_user($user) ) {
-                $user = $user_obj;
-            }
-            unless ($user) {
-                $c->log->debug("User '$user' doesn't exist in the default store")
-                    if $c->debug;
-                return;
-            }
-            $c->set_authenticated($user);
-            return 1;
-        } elsif ( $c->debug ) {
-            $c->log->info('Remote authentication failed:'.$resp->message);
-            return 0;
-        }
-    } elsif ( $c->debug ) {
-        $c->log->info('No credentials provided for basic auth');
-        return 0;
-    }
-}
-
-sub authorization_required {
-    my ( $c, %opts ) = @_;
-
-    return 1 if $c->authenticate_http_proxy;
-
-    $c->authorization_required_response( %opts );
-
-    die $Catalyst::DETACH;
-}
-
-sub authorization_required_response {
-    my ( $c, %opts ) = @_;
-    
-    $c->res->status(401);
-
-    my @opts;
-
-    if ( my $realm = $opts{realm} ) {
-        push @opts, sprintf 'realm=%s', String::Escape::qprintable($realm);
-    }
-
-    if ( my $domain = $opts{domain} ) {
-        Catalyst::Excpetion->throw("domain must be an array reference")
-          unless ref($domain) && ref($domain) eq "ARRAY";
-
-        my @uris =
-          $c->config->{authentication}{http}{use_uri_for}
-          ? ( map { $c->uri_for($_) } @$domain )
-          : ( map { URI::Escape::uri_escape($_) } @$domain );
-
-        push @opts, qq{domain="@uris"};
-    }
-
-    $c->res->headers->www_authenticate(join " ", "Basic", @opts);
-}
-
-__PACKAGE__;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Catalyst::Plugin::Authentication::Credential::HTTP::Proxy - HTTP Proxy authentication
-for Catlayst.
-
-=head1 SYNOPSIS
-
-    use Catalyst qw/
-        Authentication
-        Authentication::Store::Moose
-        Authentication::Store::Elk
-        Authentication::Credential::HTTP::Proxy
-    /;
-
-    $c->config->{authentication}{http_proxy}= {
-        url  =>'http://elkland.no/auth',
-        store => 'Authentication::Store::Moose'
-    };
-    
-    sub foo : Local { 
-        my ( $self, $c ) = @_;
-
-        $c->authorization_required( realm => "foo" ); # named after the status code ;-)
-
-        # either user gets authenticated or 401 is sent
-
-        do_stuff();
-    }
-
-    # with ACL plugin
-    __PACKAGE__->deny_access_unless("/path", sub { $_[0]->authenticate_http });
-
-    sub end : Private {
-        my ( $self, $c ) = @_;
-
-        $c->authorization_required_response( realm => "foo" );
-        $c->error(0);
-    }
-
-=head1 DESCRIPTION
-
-This moduule lets you use HTTP Proxy authentication with
-L<Catalyst::Plugin::Authentication>.
-
-Currently this module only supports the Basic scheme, but upon request Digest
-will also be added. Patches welcome!
-
-
-=head1 CONFIG
-
-This module reads config from $c->config->{authentication}{http_proxy}. The following settings
-are supported:
-
-=over 4
-
-=item url
-
-Required. A url protected with basic authentication to authenticate against.
-
-=item store
-
-To specify what store to use. will use the default store if not set.
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item authorization_required
-
-Tries to C<authenticate_http_proxy>, and if that fails calls
-C<authorization_required_response> and detaches the current action call stack.
-
-=item authenticate_http_proxy
-
-Looks inside C<< $c->request->headers >> and processes the basic (badly named)
-authorization header. Then authenticates this against the provided url.
-
-=item authorization_required_response
-
-Sets C<< $c->response >> to the correct status code, and adds the correct
-header to demand authentication data from the user agent.
-
-=back
-
-=head1 AUTHORS
-
-Marcus Ramberg <mramberg@cpan.org
-
-=head1 COPYRIGHT & LICENSE
-
-        Copyright (c) 2005 the aforementioned authors. All rights
-        reserved. This program is free software; you can redistribute
-        it and/or modify it under the same terms as Perl itself.
-
-=cut
-
diff --git a/t/kwalitee.t b/t/kwalitee.t
new file mode 100755 (executable)
index 0000000..b4d2572
--- /dev/null
@@ -0,0 +1,6 @@
+use Test::More;
+
+eval { require Test::Kwalitee; Test::Kwalitee->import() };
+
+plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@;
+
diff --git a/t/live_app.t b/t/live_app.t
new file mode 100644 (file)
index 0000000..1ff5ce5
--- /dev/null
@@ -0,0 +1,123 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+    eval { require Test::WWW::Mechanize::Catalyst }
+      or plan skip_all =>
+      "Test::WWW::Mechanize::Catalyst is needed for this test";
+    plan tests => 9;
+}
+use HTTP::Request;
+{
+    package AuthTestApp;
+    use Catalyst qw/
+      Authentication
+      /;
+    use Test::More;
+    our %users;
+    __PACKAGE__->config(authentication => {
+        default_realm => 'test_proxy',
+        realms => {
+            test => {
+                store => { 
+                    class => 'Minimal',
+                    users => \%users,
+                },
+                credential => { 
+                    class => 'HTTP', 
+                    type  => 'basic',
+                    password_type => 'clear', 
+                    password_field => 'password'
+                },
+            },
+            test_proxy => {
+                store => {
+                    class => 'Minimal',
+                    users => {
+                        foo => { password => 'proxypass' }
+                    },
+                },
+                credential => {
+                    class => 'HTTP::Proxy',
+                    url => 'http://localhost/moose',
+                    type => 'basic',
+                },
+            }
+        },
+    });
+    sub moose : Local {
+        my ( $self, $c ) = @_;
+        $c->authenticate({}, 'test');
+           $c->res->body( 'test realm:' . $c->user->id );
+    }
+    sub yak : Local {
+        my ( $self, $c ) = @_;
+        $c->authenticate({}, 'test_proxy');
+           $c->res->body( 'test_proxy realm:' . $c->user->id );
+    }
+    %users = (
+        foo => { password         => "s3cr3t", },
+    );
+    __PACKAGE__->setup;
+}
+use Test::WWW::Mechanize::Catalyst qw/AuthTestApp/;
+{
+    no warnings qw/once redefine/;
+    *Catalyst::Authentication::Credential::HTTP::Proxy::User::new = sub { Test::WWW::Mechanize::Catalyst->new };
+}
+SKIP: {
+    
+    skip 'Catalyst engine is not reenterant, this will not work', 5;
+    last;
+    
+    my $mech = Test::WWW::Mechanize::Catalyst->new;
+    {   # HTTP, no auth
+#        $mech->get("http://localhost/moose");
+        is( $mech->status, 401, "status is 401" ) or die $mech->content;
+        $mech->content_lacks( "foo", "no output" );
+    }
+    
+    {# HTTP with auth
+        my $r = HTTP::Request->new( GET => "http://localhost/moose" );
+        $r->authorization_basic(qw/foo s3cr3t/);
+#        $mech->request($r);
+        is( $mech->status, 200, "status is 200" );
+        $mech->content_contains( "test realm:foo", "test realm:foo output" );
+    }
+
+    {   # HTTP with other auth
+        my $r = HTTP::Request->new( GET => "http://localhost/moose" );
+        $r->authorization_basic(qw/foo proxypass/);
+#        $mech->request($r);
+        is( $mech->status, 401, "status is 401" ) or die $mech->content;
+    }
+}
+
+SKIP: {
+    
+    skip 'Catalyst engine is not reenterant, this will not work', 4;
+    last;
+    
+    my $mech = Test::WWW::Mechanize::Catalyst->new;
+    {   # Proxy, no auth
+#        $mech->get("http://localhost/yak");
+        is( $mech->status, 401, "status is 401" ) or die $mech->content;
+        $mech->content_lacks( "foo", "no output" );
+    }
+    
+    {   # Proxy with other auth
+        my $r = HTTP::Request->new( GET => "http://localhost/yak" );
+        $r->authorization_basic(qw/foo s3cr3t/);
+#        $mech->request($r);
+        is( $mech->status, 401, "status is 401" ) or die $mech->content;
+    }
+
+    {   # HTTP with other auth
+        my $r = HTTP::Request->new( GET => "http://localhost/yak" );
+        $r->authorization_basic(qw/foo proxypass/);
+#        $mech->request($r);
+        is( $mech->status, 200, "status is 200" );
+        $mech->content_contains( "test_proxy realm:foo", "test_proxy realm:foo output" );
+    }
+}
diff --git a/t/mock.t b/t/mock.t
new file mode 100644 (file)
index 0000000..5ba4275
--- /dev/null
+++ b/t/mock.t
@@ -0,0 +1,127 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 27;
+use Test::Exception;
+use Test::MockObject;
+
+BEGIN {
+    use_ok('Catalyst::Authentication::Credential::HTTP::Proxy');
+}
+
+my $mock_c = Test::MockObject->new;
+$mock_c->mock('debug' => sub { 0 });
+my ($authenticated_user, $authenticated);
+$mock_c->mock('set_authenticated' => sub { $authenticated_user = $_[1]; $authenticated++; });
+
+my ($auth_info, $user);
+my $mock_realm = Test::MockObject->new;
+$mock_realm->mock('find_user' => sub { $auth_info = $_[1]; return $user });
+
+throws_ok {
+    Catalyst::Authentication::Credential::HTTP::Proxy->new({}, $mock_c, $mock_realm);
+} qr/Catalyst::Authentication::Credential::HTTP::Proxy/, 'No config throws';
+
+lives_ok { 
+    Catalyst::Authentication::Credential::HTTP::Proxy->new(
+        {url => 'http://some.proxy:8080'},
+        $mock_c, $mock_realm,
+    );
+} 'Normal (with url) ok';
+
+throws_ok {
+    Catalyst::Authentication::Credential::HTTP::Proxy->new(
+        {url => 'http://some.proxy:8080',
+        type => 'foobar'},
+        $mock_c, $mock_realm,
+    );
+} qr/Catalyst::Authentication::Credential::HTTP::Proxy/, 'Asking for unknown type throws';
+
+my $log = Test::MockObject->new;
+$log->mock('info' => sub {});
+$log->mock('debug' => sub {});
+my $req = Test::MockObject->new;
+my $req_headers = HTTP::Headers->new;
+my $res = Test::MockObject->new;
+$req->set_always( headers => $req_headers );
+my $status;
+$res->mock(status => sub { $status = $_[1] });
+my $content_type;
+$res->mock(content_type => sub { $content_type = $_[1] });
+my $body;
+my $headers;
+$res->mock(body => sub { $body = $_[1] });
+my $res_headers = HTTP::Headers->new;
+$res->set_always( headers => $res_headers );
+$mock_c->set_always( debug => 0 );
+$mock_c->set_always( config => {} );
+$mock_c->set_always( req => $req );
+$mock_c->set_always( res => $res );
+$mock_c->set_always( request => $req );
+$mock_c->set_always( response => $res );
+$mock_c->set_always( log => $log );
+
+$mock_realm->set_always(name => 'myrealm');
+
+my $cred = Catalyst::Authentication::Credential::HTTP::Proxy->new(
+    {url => 'http://some.proxy:8080',
+    type => 'basic'},
+    $mock_c, $mock_realm,
+);
+
+ok(!$cred->authenticate_basic($mock_c, $mock_realm, {}), '_authenticate_basic returns false with no auth headers');
+throws_ok {
+    $cred->authenticate($mock_c, $mock_realm, {});
+} qr/^$Catalyst::DETACH$/, '$cred->authenticate calls detach';
+
+like( ($res_headers->header('WWW-Authenticate'))[0], qr/^Basic/, "WWW-Authenticate header set: basic");
+like( ($res_headers->header('WWW-Authenticate'))[0], qr/realm="myrealm"/, "WWW-Authenticate header set: basic realm");
+
+$res_headers->clear;
+
+$req_headers->authorization_basic( qw/Mufasa password/ );
+my ($auth_ua, $auth_res, $auth_url);
+{
+    no warnings qw/redefine once/;
+    *Catalyst::Authentication::Credential::HTTP::Proxy::User::get = sub { $auth_ua = shift; $auth_url = shift; $auth_res };
+}
+$auth_res = HTTP::Response->new;
+$auth_res->code(500);
+$auth_res->message('FAIL');
+
+ok(!$cred->authenticate_basic($mock_c, $mock_realm, {}), '_authenticate_basic returns false with auth response !success');
+is_deeply([$auth_ua->get_basic_credentials], [qw/Mufasa password/], 'Basic auth in useragent is Mufasa/password');
+is($auth_url, 'http://some.proxy:8080', 'get http://some.proxy:8080');
+throws_ok {
+    $cred->authenticate($mock_c, $mock_realm, {});
+} qr/^$Catalyst::DETACH$/, '$cred->authenticate calls detach with auth response !success';
+
+like( ($res_headers->header('WWW-Authenticate'))[0], qr/^Basic/, "WWW-Authenticate header set: basic");
+like( ($res_headers->header('WWW-Authenticate'))[0], qr/realm="myrealm"/, "WWW-Authenticate header set: basic realm");
+
+$res_headers->clear;
+$auth_res->code(200);
+($auth_url, $auth_ua) = (undef, undef);
+
+ok(!$cred->authenticate_basic($mock_c, $mock_realm, {}), '_authenticate_basic returns false with auth response success but no user from realm');
+is_deeply([$auth_ua->get_basic_credentials], [qw/Mufasa password/], 'Basic auth in useragent is Mufasa/password');
+is($auth_url, 'http://some.proxy:8080', 'get http://some.proxy:8080');
+is_deeply($auth_info, { username => 'Mufasa'}, '$realm->find_user({ username => "Mufasa" })');
+ok(!$authenticated, 'Not set_authenticated');
+throws_ok {
+    $cred->authenticate($mock_c, $mock_realm, {});
+} qr/^$Catalyst::DETACH$/, '$cred->authenticate calls detach with auth response !success';
+
+($auth_url, $auth_ua) = (undef, undef);
+$res_headers->clear;
+$user = Test::MockObject->new;
+
+ok($cred->authenticate_basic($mock_c, $mock_realm, {}), '_authenticate_basic returns true with auth response success and user from realm');
+is_deeply([$auth_ua->get_basic_credentials], [qw/Mufasa password/], 'Basic auth in useragent is Mufasa/password');
+is_deeply($auth_info, { username => 'Mufasa'}, '$realm->find_user({ username => "Mufasa" })');
+ok($authenticated, 'Called set_authenticated');
+is("$authenticated_user", "$user", 'Called set_authenticated with user object');
+lives_ok {
+    $cred->authenticate($mock_c, $mock_realm, {});
+} '$cred->authenticate does not detach';
+ok(!$res_headers->header('WWW-Authenticate'), 'No authenticate header on successful auth');
diff --git a/t/use.t b/t/use.t
new file mode 100644 (file)
index 0000000..c53acaa
--- /dev/null
+++ b/t/use.t
@@ -0,0 +1,9 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 2;
+
+BEGIN {
+    use_ok('Catalyst::Authentication::Credential::HTTP::Proxy');
+    use_ok('Catalyst::Authentication::Credential::HTTP::Proxy::User');
+}