# This file documents the revision history for Perl extension Catalyst.
-5.71000_01 UNRELEASED
- - Add failing test for passing arguments to visited chained
- actions (Radoslaw Zielinski)
- - Support Moose components so that attribute defaults work
- and BUILD methods are correctly called (t0m)
- - Add tests for this (Florian Ragwitz)
-
-5.71000 2009-01-19 17:50:00
++ - Add Catalyst::Test::crequest to return both HTTP::Response object
++ & $c for local requests (kane)
+ - debug() POD rewrite (jhannah)
+ - Change the warning when you have conflicting components to
+ present a list (t0m)
+ - Move NEXT use and testing deprecated features out to its own
+ test application so that the main TestApp isn't polluted with
+ spurious warnings (t0m)
+ - Add a warning for the old ::[MVC]:: style naming scheme (t0m)
+ - Test for this (t0m)
+ - Kill Class::C3::Adopt::NEXT warnings for the Catalyst:: namespace
+ in production versions (t0m)
+ - Make MyApp.pm restartable by unsetting setup_finished in
+ the restarter process (t0m)
+ - Non-naive implementation of making mutable on restart using
+ B::Hooks::OP::Check::StashChange if installed (t0m)
+ - Tests for this (t0m)
+ - Naive implementation of making all components mutable in the
+ forked restart watcher process so native Moose apps using
+ immutable restart correctly. (t0m)
+ - Tests for this (t0m)
+ - Bump Moose dependency to 0.70 so that we avoid nasty surprises
+ with is_class_loaded and perl 5.80 when you Moosify MyApp.pm (t0m)
+ - Clarify that request arguments aren't unescaped automatically
+ (Simon Bertrang) (Closes RT#41153)
+ - Don't require C3 for the MRO test (rafl)
+ - Bump MX::Emulate::CAF prereq to support list assignment (rafl)
+ - Remove useless column in chained action debug table. (rafl)
+ - namespace::clean related cleanups (rafl)
+ - Import related cleanups and consistency fixes (rafl)
+ - Fix test suite TestApp /dump/env action (t0m)
+
+5.8000_06 2009-02-04 21:00
+ - Disallow writing to config after setup (rafl)
+ - Disallow calling setup more than once (rafl)
+ - Documentation fix regarding overloading of Engine and Dispatcher
+ instances (rafl)
+ - Several documentation typo fixes (rafl)
+ - Stop Makefile.PL from warning about versions that fixed a conflict
+ (t0m)
+ - Improved upgrading documentation (t0m, rafl)
+ - Seed the RNG in each FastCGI child process (Andrew Rodland)
+ - Properly report dynamic bind port for the development server (rafl)
+ (Closes RT#38544)
+ - Use the way documented by IO::Socket::INET to get the error message
+ after trying to create a listening socket (rafl) (Closes RT#41828)
+ - Don't ignore SIGCHLD while handling requests with the dev server
+ (rafl) (Closes RT#42962)
+
+5.8000_05 2008-29-01 00:00
- Text::SimpleTable's go as wide as $ENV{COLUMNS} (jhannah)
Patch written by Oleg Kostyuk <cub.uanic@gmail.com>
- - backport go doc patch
- - added ru/ua translations to error page
- - backport stripping build_requires
-
-5.7099_04 2009-01-12 13:06:00
- - Add environment hack for FastCGI under IIS (Simon Bertrang)
- - Test for this and preexisting Lighty hack (Simon Bertrang)
- - Change streaming test to serve itself rather than 01use.t, making test
- sync for engines easier (t0m)
+ - Improve docs for visit (mateu)
+ - Add docs for finalize hook (dhoss)
+ - Added ru/ua translations to error page
+ - Improve the clarity and verbosity of the warning when component
+ resolution uses regex fallback. (jhannah)
+ - Handle leading CRLF in HTTP requests sometimes sent by IE6 in
+ keep-alive requests. (andyg)
+ - Fixes for FastCGI with IIS 6.0 (janus)
+ - Passing request method exported by Catalyst::Test an extra
+ parameter used to be ignored, but started breaking if the parameter
+ was not a hash in 5.8000_04. Extra parameter is now ignored if
+ it isn't a hashref (t0m)
+ - Fix request argumentss getting corrupted if you override the
+ dispatcher and call an action which detaches (for
+ Catalyst::Plugin::Authorization::ACL) (t0m)
+ - Fix calling use Catalyst::Test 'MyApp' 'foo' which used to work,
+ but stopped as the 2nd parameter can be an options hash now (t0m)
+ - Bump Moose dependency to fix make_immutable bug (t0m)
+ - Use compile time extends in Catalyst::Controller (t0m)
+ - Make Catalyst::Request::uploads attribute non-lazy, to fix
+ test for Catalyst-Engine-Apache (t0m)
+ - Bump version of MooseX::Emulate::Class::Accessor::Fast (t0m)
+ - Stop using MooseX::Adopt::Class::Accessor::Fast by default, to stop
+ breaking other packages which use Class::Accessor::Fast
+ - Remove unused action_container_class attribute from
+ Catalyst::Dispatcher (t0m)
+ - Replace {_body} instance access with calls to _body accessors (t0m)
+ - Add backwards compatibility alias methods for private attributes on
+ Catalyst::Dispatcher which used to be public. Needed by
+ Catalyst::Plugin::Server and Catalyst::Plugin::Authorization::ACL
+ (t0m)
+ - Fix return value of $c->req->body, which delegates to the body
+ method on the requests HTTP::Body instance (t0m)
+ - Test for this (t0m)
+ - Fix calling $c->req->body from inside an overridden prepare_action
+ method in a plugin, as used by Catalyst::Plugin::Server (t0m)
+ - Test for this (t0m)
+ - Fix assignment to Catalyst::Dispatcher's preload_dispatch_types and
+ postload_dispatch_types attributes - assigning a list should later
+ return a listref. Fixes Catalyst::Plugin::Server. (t0m)
+ - Tests for this (t0m)
+ - Change streaming test to serve itself rather than 01use.t, making
+ test sync for engines easier (t0m)
+ - Refactor capturing of $app from Catalyst::Controller into
+ Catalyst::Component::ApplicationAttribute for easier reuse in other
+ components (Florian Ragwitz)
+ - Make the test suites YAML dependency optional (Florian Ragwitz)
+ - Make debug output show class name for the engine and dispatcher
+ rather than the stringified ref. (t0m)
+ - Make MyApp immutable at the end of the scope after the setup
+ method is called, fixing issues with plugins which have their
+ own new methods by inlining a constructor on MyApp (t0m)
+ - Test for this and method modifiers in MyApp (t0m)
+ - Fix bug causing Catalyst::Request::Upload's basename method
+ to return undef (t0m)
+ - Test for this (Carl Franks)
+ - Fix loading of classes which do not define any symbols to not
+ die, as it didn't in 5.70 (t0m)
+ - Test for this (t0m)
+ - Bump MooseX::Emulate::Class::Accessor::Fast dependency
+ to force new version which fixes a lot of plugins (t0m)
+ - Make log levels additive, and add documentation and tests
+ for the setup_log method, which previously had none.
+ Sewn together by t0m from two patches provided by David E. Wheeler
+ - Switch an around 'new' in Catalyst::Controller to a BUILDARGS
+ method as it's much neater and more obvious what is going on (t0m)
+ - Add a clearer method on request and response _context
+ attributes, and use if from ::Engine rather than deleting
+ the key from the instance hash (t0m)
+ - Use handles on tree attribute of Catalyst::Stats to replace
+ trivial delegation methods (t0m)
+ - Change the following direct hash accesses into attributes:
+ Catalyst::Engine: _prepared_write
+ Catalyst::Engine::CGI: _header_buf
+ Catalyst::Engine::HTTP: options, _keepalive, _write_error
+ Catalyst::Request: _path
+ Catalyst::Stats: tree
+ (t0m)
+ - Fix issues in Catalyst::Controller::WrapCGI
+ and any other components which import (or define) their
+ own meta method by always explicitly calling
+ Class::MOP::Object->meta inside Catalyst (t0m)
+ - Add test for this (t0m)
+ - Add test case for the bug which is causing the
+ Catalyst::Plugin::Authentication tests to fail (t0m)
+ - Fix a bug in uri_for which could cause it to generate paths
+ with multiple slashes in them. (t0m)
+ - Add test for this (t0m)
+ - Fix SKIP block name in t/optional_http-server-restart.t,
+ stopping 'Label not found for "last SKIP"' error from
+ Test::More (t0m)
+ - Workaround max_redirect 0 bug in LWP (andyg)
+ - Move live_engine_response_print into aggregate (andyg)
+ - Fix dependency bug, s/parent/base/ in new test (rafl)
+ - Fix optional tests to run the live tests in the aggregate
+ dir (andyg)
+ - Fix Catalyst->go error in remote tests (andyg)
+ - Fix upload test to work with remote servers, don't check for
+ deleted files (andyg)
+ - Fix engine_request_uri tests to work on remote server with
+ different URI (andyg)
+
+5.8000_04 2008-12-05 12:15:00
+ - Silence Class::C3::Adopt::NEXT warnings in the test suite (rafl)
+ - Fix loads of 'used once, possible typo' warnings (rafl)
+ - Additional tests to ensure upload temp files are deleted (andyg)
+ - Remove use of NEXT from the test suite, except for one case
+ which tests if Class::C3::Adopt::NEXT is working (t0m)
+ - Use a predicate to avoid recursion in cases where the uri
+ method is overridden by a plugin, and calls the base method,
+ for example Catalyst::Plugin::SmartURI (t0m)
+ - Test for this (caelum)
+ - Compose the MooseX::Emulate::Class::Accessor::Fast role to
+ Catalyst::Action, Catalyst::Request, and all other modules which
+ inherit from Class::Accessor::Fast in 5.70.
+ This fixes:
+ - Catalyst::Controller::HTML::FormFu (zamolxes)
+ - Catalyst::Request::REST (t0m)
+ - Test for this (t0m)
+ - Make hostname resolution lazy (Marc Mims)
+ - Support mocking virtualhosts in test suite (Jason Gottshall)
+ - Add README (marcus)
+ - Fix TODO list (t0m)
+ - Use Class::C3::Adopt::NEXT (rafl)
+ - Ignore C3 warnings on 5.10 when testing ensure_class_loaded (rafl)
+ - Add TODO test for chained bug (gbjk)
+ - Fix list address in documentation (zarquon)
+ - Fix ACCEPT_CONTEXT on MyApp, called as a class method (marcus)
+ - Test for this (marcus)
+ - Bump MooseX::Emulate::Class::Accessor::Fast version requirement to
+ get more back compatibility (t0m)
+ - Improve documentation for $req->captures (caelum)
+ - Fix a bug in Catalyst::Stats, stopping garbage being inserted into
+ the stats if a user calls begin => but no end => (jhannah)
+ - Test for this (jhannah)
+ - Trim lines sooner in stats to avoid ugly Text::SimpleTable wrapping
+ (jhannah)
+ - Change Catalyst::ClassData to tweak the symbol table inline for
+ performance after profiling (mst)
+ - Fix POD typo in finalize_error (jhannah)
+ - Add tests to ensure that we delete the temp files created by
+ HTTP::Body's OctetStream parser (t0m)
+
+5.8000_03 2008-10-14 14:13:00
+ - Fix forwarding to Catalyst::Action objects (Rafael Kitover).
+ - Fix links to the mailing lists (RT #39754 and Florian Ragwitz).
+ - Use Class::MOP instead of Class::Inspector (Florian Ragwitz).
+ - Change Catalyst::Test to use Sub::Exporter (Florian Ragwitz).
+ - Fixed typo in Engine::HTTP::Restarter::Watcher causing -r to complain.
+
+5.8000_02 2008-10-14 07:59:00
+ - Fix manifest
+
+5.8000_01 2008-10-13 22:52:00
+ - Port to Moose
+ - Added test for action stringify
+ - Added test for component instances getting $self->{value} from config.
+ - Add Catalyst::Response->print() method (ilmari)
+ - Optionally aggregate tests using Test::Aggregate (Florian Ragwitz).
+ - Additional docs for uri_for to mention how to use $c->action and
+ $c->req->captures (jhannah)
+ - List unattached chained actions in Debug mode (Florian Ragwitz).
+ - Pod formatting fix for Engine::FastCGI (Oleg Kostyuk).
+ - Add visit, a returning ->go
+
+5.7XXXXXX XXXX
- Workaround change in LWP that broke a cookie test (RT #40037)
- - Backport go() from 5.8 branch.
+ - Back out go() since that feature's been pushed to 5.80
- Fix some Win32 test failures
- Add pt translation of error message (wreis)
- Make :Chained('../action') work (Florian Ragwitz)
use Catalyst::Exception;
use Catalyst::Utils;
-use Class::Inspector;
+use Class::MOP;
+use Sub::Exporter;
+
+my $build_exports = sub {
+ my ($self, $meth, $args, $defaults) = @_;
+
+ my $request;
+ my $class = $args->{class};
+
+ if ( $ENV{CATALYST_SERVER} ) {
+ $request = sub { remote_request(@_) };
+ } elsif (! $class) {
+ $request = sub { Catalyst::Exception->throw("Must specify a test app: use Catalyst::Test 'TestApp'") };
+ } else {
+ unless (Class::MOP::is_class_loaded($class)) {
+ Class::MOP::load_class($class);
+ }
+ $class->import;
+
+ $request = sub { local_request( $class, @_ ) };
+ }
+
+ my $get = sub { $request->(@_)->content };
+
++ my $crequest = sub {
++ my $me = ref $self || $self;
++
++ ### throw an exception if crequest is being used against a remote
++ ### server
++ Catalyst::Exception->throw("$me only works with local requests, not remote")
++ if $ENV{CATALYST_SERVER};
++
++ ### place holder for $c after the request finishes; reset every time
++ ### requests are done.
++ my $c;
++
++ ### hook into 'dispatch' -- the function gets called after all plugins
++ ### have done their work, and it's an easy place to capture $c.
++ no warnings 'redefine';
++ my $dispatch = Catalyst->can('dispatch');
++ local *Catalyst::dispatch = sub {
++ $c = shift;
++ $dispatch->( $c, @_ );
++ };
++
++ ### do the request; C::T::request will know about the class name, and
++ ### we've already stopped it from doing remote requests above.
++ my $res = $request->( @_ );
++
++ ### return both values
++ return ( $res, $c );
++ };
++
+ return {
- request => $request,
- get => $get,
++ request => $request,
++ get => $get,
++ crequest => $crequest,
+ content_like => sub {
+ my $action = shift;
+ return Test::More->builder->like($get->($action),@_);
+ },
+ action_ok => sub {
+ my $action = shift;
+ return Test::More->builder->ok($request->($action)->is_success, @_);
+ },
+ action_redirect => sub {
+ my $action = shift;
+ return Test::More->builder->ok($request->($action)->is_redirect,@_);
+ },
+ action_notfound => sub {
+ my $action = shift;
+ return Test::More->builder->is_eq($request->($action)->code,404,@_);
+ },
+ contenttype_is => sub {
+ my $action = shift;
+ my $res = $request->($action);
+ return Test::More->builder->is_eq(scalar($res->content_type),@_);
+ },
+ };
+};
+
+our $default_host;
+
+{
+ my $import = Sub::Exporter::build_exporter({
+ groups => [ all => $build_exports ],
+ into_level => 1,
+ });
+
+
+ sub import {
+ my ($self, $class, $opts) = @_;
+ $import->($self, '-all' => { class => $class });
+ $opts = {} unless ref $opts eq 'HASH';
+ $default_host = $opts->{default_host} if exists $opts->{default_host};
++ return 1;
+ }
+}
=head1 NAME
is ( $uri->path , '/y');
my $content = get($uri->path);
- =head2 request
+ =head2 $res = request( ... );
-Returns a C<HTTP::Response> object.
+Returns a C<HTTP::Response> object. Accepts an optional hashref for request
+header configuration; currently only supports setting 'host' value.
my $res = request('foo/bar?test=1');
+ my $virtual_res = request('foo/bar?test=1', {host => 'virtualhost.com'});
- =head2 local_request
+ =head1 FUNCTIONS
+
+ =head2 ($res, $c) = crequest( ... );
+
+ Works exactly like C<Catalyst::Test::request>, except it also returns the
+ catalyst context object, C<$c>. Note that this only works for local requests.
+
-=cut
-
-sub import {
- my $self = shift;
- my $class = shift;
-
- my ( $get, $request );
-
- if ( $ENV{CATALYST_SERVER} ) {
- $request = sub { remote_request(@_) };
- $get = sub { remote_request(@_)->content };
- } elsif (! $class) {
- $request = sub { Catalyst::Exception->throw("Must specify a test app: use Catalyst::Test 'TestApp'") };
- $get = $request;
- } else {
- unless( Class::Inspector->loaded( $class ) ) {
- require Class::Inspector->filename( $class );
- }
- $class->import;
-
- $request = sub { local_request( $class, @_ ) };
- $get = sub { local_request( $class, @_ )->content };
- }
-
- no strict 'refs';
- my $caller = caller(0);
-
- *{"$caller\::request"} = $request;
- *{"$caller\::get"} = $get;
- *{"$caller\::crequest"} = sub {
- my $me = ref $self || $self;
-
- ### throw an exception if crequest is being used against a remote
- ### server
- Catalyst::Exception->throw("$me only works with local requests, not remote")
- if $ENV{CATALYST_SERVER};
-
- ### place holder for $c after the request finishes; reset every time
- ### requests are done.
- my $c;
-
- ### hook into 'dispatch' -- the function gets called after all plugins
- ### have done their work, and it's an easy place to capture $c.
- no warnings 'redefine';
- my $dispatch = Catalyst->can('dispatch');
- local *Catalyst::dispatch = sub {
- $c = shift;
- $dispatch->( $c, @_ );
- };
-
- ### do the request; C::T::request will know about the class name, and
- ### we've already stopped it from doing remote requests above.
- my $res = $request->( @_ );
-
- ### return both values
- return ( $res, $c );
- };
-}
-
+ =head2 $res = Catalyst::Test::local_request( $AppClass, $url );
Simulate a request using L<HTTP::Request::AsCGI>.
use strict;
use warnings;
- use Test::More;
+ use FindBin;
+ use lib "$FindBin::Bin/lib";
-use Test::More tests => 48;
-
++use Test::More tests => 56;
+use FindBin qw/$Bin/;
+use lib "$Bin/lib";
+use Catalyst::Utils;
+use HTTP::Request::Common;
+use Test::Exception;
- plan tests => 11;
+ my $Class = 'Catalyst::Test';
+ my $App = 'TestApp';
+ my $Pkg = __PACKAGE__;
+ my $Url = 'http://localhost/';
+ my $Content = "root index";
- use_ok('Catalyst::Test');
+ my %Meth = (
+ $Pkg => [qw|get request crequest|], # exported
+ $Class => [qw|local_request remote_request|], # not exported
+ );
- eval "get('http://localhost')";
- isnt( $@, "", "get returns an error message with no app specified");
+ ### make sure we're not trying to connect to a remote host -- these are local tests
+ local $ENV{CATALYST_SERVER};
- eval "request('http://localhost')";
- isnt( $@, "", "request returns an error message with no app specified");
+ use_ok( $Class );
+
+ ### check available methods
+ { ### turn of redefine warnings, we'll get new subs exported
+ ### XXX 'no warnings' and 'local $^W' wont work as warnings are turned on in
+ ### test.pm, so trap them for now --kane
+ { local $SIG{__WARN__} = sub {};
+ ok( $Class->import, "Argumentless import for methods only" );
+ }
+
+ while( my($class, $meths) = each %Meth ) {
+ for my $meth ( @$meths ) { SKIP: {
+
+ ### method available?
+ can_ok( $class, $meth );
+
+ ### only for exported methods
+ skip "Error tests only for exported methods", 2 unless $class eq $Pkg;
+
+ ### check error conditions
+ eval { $class->can($meth)->( $Url ) };
+ ok( $@, " $meth without app gives error" );
+ like( $@, qr/$Class/,
+ " Error filled with expected content for '$meth'" );
+ } }
+ }
+ }
+
+ ### simple tests for exported methods
+ { ### turn of redefine warnings, we'll get new subs exported
+ ### XXX 'no warnings' and 'local $^W' wont work as warnings are turned on in
+ ### test.pm, so trap them for now --kane
+ { local $SIG{__WARN__} = sub {};
+ ok( $Class->import( $App ),
+ "Loading $Class for App $App" );
+ }
+
+ ### test exported methods again
+ for my $meth ( @{ $Meth{$Pkg} } ) { SKIP: {
+
+ ### do a call, we should get a result and perhaps a $c if it's 'crequest';
+ my ($res, $c) = eval { $Pkg->can($meth)->( $Url ) };
+
+ ok( 1, " Called $Pkg->$meth( $Url )" );
+ ok( !$@, " No critical error $@" );
+ ok( $res, " Result obtained" );
+
+ ### get the content as a string, to make sure we got what we expected
+ my $res_as_string = $meth eq 'get' ? $res : $res->content;
+ is( $res_as_string, $Content,
+ " Content as expected: $res_as_string" );
+
+ ### some tests for 'crequest'
+ skip "Context tests skipped for '$meth'", 6 unless $meth eq 'crequest';
+
+ ok( $c, " Context object returned" );
+ isa_ok( $c, $App, " Object" );
+ is( $c->request->uri, $Url,
+ " Url recorded in request" );
+ is( $c->response->body, $Content,
+ " Content recorded in response" );
+ ok( $c->stash, " Stash accessible" );
+ ok( $c->action, " Action object accessible" );
+ } }
+ }
+
+# FIXME - These vhosts in tests tests should be somewhere else...
+
+sub customize { Catalyst::Test::_customize_request(@_) }
+
+{
+ my $req = Catalyst::Utils::request('/dummy');
+ customize( $req );
+ is( $req->header('Host'), undef, 'normal request is unmodified' );
+}
+
+{
+ my $req = Catalyst::Utils::request('/dummy');
+ customize( $req, { host => 'customized.com' } );
+ like( $req->header('Host'), qr/customized.com/, 'request is customizable via opts hash' );
+}
+
+{
+ my $req = Catalyst::Utils::request('/dummy');
+ local $Catalyst::Test::default_host = 'localized.com';
+ customize( $req );
+ like( $req->header('Host'), qr/localized.com/, 'request is customizable via package var' );
+}
+
+{
+ my $req = Catalyst::Utils::request('/dummy');
+ local $Catalyst::Test::default_host = 'localized.com';
+ customize( $req, { host => 'customized.com' } );
+ like( $req->header('Host'), qr/customized.com/, 'opts hash takes precedence over package var' );
+}
+
+{
+ my $req = Catalyst::Utils::request('/dummy');
+ local $Catalyst::Test::default_host = 'localized.com';
+ customize( $req, { host => '' } );
+ is( $req->header('Host'), undef, 'default value can be temporarily cleared via opts hash' );
+}
+
+# Back compat test, extra args used to be ignored, now a hashref of options.
+use_ok('Catalyst::Test', 'TestApp', 'foobar');
+
+# Back compat test, ensure that request ignores anything which isn't a hash.
+lives_ok {
+ request(GET('/dummy'), 'foo');
+} 'scalar additional param to request method ignored';
+lives_ok {
+ request(GET('/dummy'), []);
+} 'array additional param to request method ignored';
++