Hello community,

here is the log from the commit of package perl-Mojolicious for 
openSUSE:Factory checked in at 2017-08-19 10:55:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Mojolicious.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Mojolicious"

Sat Aug 19 10:55:44 2017 rev:73 rq:517491 version:7.42

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes        
2017-08-06 11:25:37.924915911 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Mojolicious.new/perl-Mojolicious.changes   
2017-08-19 10:55:45.534029326 +0200
@@ -1,0 +2,30 @@
+Fri Aug 18 05:48:34 UTC 2017 - [email protected]
+
+- updated to 7.42
+   see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+  7.42  2017-08-17
+    - Improved Mojo::Base role support with shorthands.
+        MyClass->with_roles('MyClass::Role::Foo')
+      becomes
+        MyClass->with_roles('+Foo')
+  
+  7.41  2017-08-15
+    - Added with_roles method to Mojo::ByteStream, Mojo::Collection, Mojo::DOM 
and
+      Mojo::File.
+
+-------------------------------------------------------------------
+Tue Aug 15 05:49:47 UTC 2017 - [email protected]
+
+- updated to 7.40
+   see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+  7.40  2017-08-14
+    - Added support for Role::Tiny extensions to all classes based on 
Mojo::Base.
+      (dotan)
+    - Added with_roles method to Mojo::Base. (dotan)
+    - Added the guide Mojolicious::Guides::Testing. (scottw)
+    - Replaced systemd detection in Mojo::Log with the MOJO_LOG_SHORT 
environment
+      variable, since there is no reliable way to detect systemd.
+
+-------------------------------------------------------------------

Old:
----
  Mojolicious-7.39.tar.gz

New:
----
  Mojolicious-7.42.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Mojolicious.spec ++++++
--- /var/tmp/diff_new_pack.qDeHtf/_old  2017-08-19 10:55:47.433761471 +0200
+++ /var/tmp/diff_new_pack.qDeHtf/_new  2017-08-19 10:55:47.445759779 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           perl-Mojolicious
-Version:        7.39
+Version:        7.42
 Release:        0
 %define cpan_name Mojolicious
 Summary:        Real-time web framework

++++++ Mojolicious-7.39.tar.gz -> Mojolicious-7.42.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/Changes new/Mojolicious-7.42/Changes
--- old/Mojolicious-7.39/Changes        2017-08-03 10:38:56.000000000 +0200
+++ new/Mojolicious-7.42/Changes        2017-08-17 13:14:25.000000000 +0200
@@ -1,4 +1,22 @@
 
+7.42  2017-08-17
+  - Improved Mojo::Base role support with shorthands.
+      MyClass->with_roles('MyClass::Role::Foo')
+    becomes
+      MyClass->with_roles('+Foo')
+
+7.41  2017-08-15
+  - Added with_roles method to Mojo::ByteStream, Mojo::Collection, Mojo::DOM 
and
+    Mojo::File.
+
+7.40  2017-08-14
+  - Added support for Role::Tiny extensions to all classes based on Mojo::Base.
+    (dotan)
+  - Added with_roles method to Mojo::Base. (dotan)
+  - Added the guide Mojolicious::Guides::Testing. (scottw)
+  - Replaced systemd detection in Mojo::Log with the MOJO_LOG_SHORT environment
+    variable, since there is no reliable way to detect systemd.
+
 7.39  2017-08-03
   - Removed experimental close_idle_connections method from
     Mojo::Server::Daemon.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/MANIFEST 
new/Mojolicious-7.42/MANIFEST
--- old/Mojolicious-7.39/MANIFEST       2017-08-03 10:48:59.000000000 +0200
+++ new/Mojolicious-7.42/MANIFEST       2017-08-17 13:15:13.000000000 +0200
@@ -101,6 +101,7 @@
 lib/Mojolicious/Guides/Growing.pod
 lib/Mojolicious/Guides/Rendering.pod
 lib/Mojolicious/Guides/Routing.pod
+lib/Mojolicious/Guides/Testing.pod
 lib/Mojolicious/Guides/Tutorial.pod
 lib/Mojolicious/Lite.pm
 lib/Mojolicious/Plugin.pm
@@ -214,6 +215,7 @@
 t/mojo/request.t
 t/mojo/request_cgi.t
 t/mojo/response.t
+t/mojo/roles.t
 t/mojo/subprocess.t
 t/mojo/template.t
 t/mojo/templates/exception.mt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/META.json 
new/Mojolicious-7.42/META.json
--- old/Mojolicious-7.39/META.json      2017-08-03 10:48:59.000000000 +0200
+++ new/Mojolicious-7.42/META.json      2017-08-17 13:15:13.000000000 +0200
@@ -58,6 +58,6 @@
       },
       "x_IRC" : "irc://irc.perl.org/#mojo"
    },
-   "version" : "7.39",
+   "version" : "7.42",
    "x_serialization_backend" : "JSON::PP version 2.94"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/META.yml 
new/Mojolicious-7.42/META.yml
--- old/Mojolicious-7.39/META.yml       2017-08-03 10:48:59.000000000 +0200
+++ new/Mojolicious-7.42/META.yml       2017-08-17 13:15:13.000000000 +0200
@@ -31,5 +31,5 @@
   homepage: http://mojolicious.org
   license: http://www.opensource.org/licenses/artistic-license-2.0
   repository: https://github.com/kraih/mojo.git
-version: '7.39'
+version: '7.42'
 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/Base.pm 
new/Mojolicious-7.42/lib/Mojo/Base.pm
--- old/Mojolicious-7.39/lib/Mojo/Base.pm       2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/Base.pm       2017-08-16 23:39:42.000000000 
+0200
@@ -11,6 +11,10 @@
 # Only Perl 5.14+ requires it on demand
 use IO::Handle ();
 
+# Role support requires Role::Tiny 2.000001+
+use constant ROLES =>
+  !!(eval { require Role::Tiny; Role::Tiny->VERSION('2.000001'); 1 });
+
 # Supported on Perl 5.22+
 my $NAME
   = eval { require Sub::Util; Sub::Util->can('set_subname') } || sub { $_[1] };
@@ -101,6 +105,13 @@
   return $self;
 }
 
+sub with_roles {
+  Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES;
+  my $class = shift;
+  return Role::Tiny->create_class_with_roles($class,
+    map { /^\+(.+)$/ ? "${class}::Role::$1" : $_ } @_);
+}
+
 1;
 
 =encoding utf8
@@ -158,7 +169,6 @@
   use utf8;
   use feature ':5.10';
   use IO::Handle ();
-  use Mojo::Base;
   push @ISA, 'Mojo::Base';
   sub has { Mojo::Base::attr(__PACKAGE__, @_) }
 
@@ -170,7 +180,6 @@
   use IO::Handle ();
   require SomeBaseClass;
   push @ISA, 'SomeBaseClass';
-  use Mojo::Base;
   sub has { Mojo::Base::attr(__PACKAGE__, @_) }
 
 =head1 FUNCTIONS
@@ -238,6 +247,20 @@
   # Inject side effects into a method chain
   $object->foo('A')->tap(sub { say $_->foo })->foo('B');
 
+=head2 with_roles
+
+  my $new_class = SubClass->with_roles('SubClass::Role::One');
+  my $new_class = SubClass->with_roles('+One', '+Two');
+
+Create and return a new class that extends the given class with one or more
+L<Role::Tiny> roles. For roles following the naming scheme
+C<MyClass::Role::RoleName> you can use the shorthand C<+RoleName>. Note that
+role support depends on L<Role::Tiny> (2.000001+).
+
+  # Create a new class with the role "SubClass::Role::Foo" and instantiate it
+  my $new_class = SubClass->with_roles('+Foo');
+  my $object    = $new_class->new;
+
 =head1 SEE ALSO
 
 L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicious.org>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/ByteStream.pm 
new/Mojolicious-7.42/lib/Mojo/ByteStream.pm
--- old/Mojolicious-7.39/lib/Mojo/ByteStream.pm 2017-07-21 09:56:39.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/ByteStream.pm 2017-08-16 23:41:01.000000000 
+0200
@@ -56,6 +56,8 @@
 
 sub to_string { ${$_[0]} }
 
+sub with_roles { shift->Mojo::Base::with_roles(@_) }
+
 sub _delegate {
   my ($self, $sub) = (shift, shift);
   $$self = $sub->(shift || 'UTF-8', $$self);
@@ -328,6 +330,13 @@
   # "&lt;html&gt;"
   b('%3Chtml%3E')->url_unescape->xml_escape;
 
+=head2 with_roles
+
+  my $new_class = Mojo::ByteStream->with_roles('Mojo::ByteStream::Role::One');
+  my $new_class = Mojo::ByteStream->with_roles('+One', '+Two');
+
+Alias for L<Mojo::Base/"with_roles">.
+
 =head2 xml_escape
 
   $stream = $stream->xml_escape;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/Collection.pm 
new/Mojolicious-7.42/lib/Mojo/Collection.pm
--- old/Mojolicious-7.39/lib/Mojo/Collection.pm 2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/Collection.pm 2017-08-16 23:40:47.000000000 
+0200
@@ -99,6 +99,8 @@
   return $self->new(grep { !$seen{$_}++ } @$self);
 }
 
+sub with_roles { shift->Mojo::Base::with_roles(@_) }
+
 sub _flatten {
   map { _ref($_) ? _flatten(@$_) : $_ } @_;
 }
@@ -367,6 +369,13 @@
   # "[[1, 2], [2, 1]]"
   c([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] })->to_array;
 
+=head2 with_roles
+
+  my $new_class = Mojo::Collection->with_roles('Mojo::Collection::Role::One');
+  my $new_class = Mojo::Collection->with_roles('+One', '+Two');
+
+Alias for L<Mojo::Base/"with_roles">.
+
 =head1 SEE ALSO
 
 L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicious.org>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/DOM.pm 
new/Mojolicious-7.42/lib/Mojo/DOM.pm
--- old/Mojolicious-7.39/lib/Mojo/DOM.pm        2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/DOM.pm        2017-08-16 23:41:23.000000000 
+0200
@@ -13,7 +13,7 @@
 use Mojo::Collection;
 use Mojo::DOM::CSS;
 use Mojo::DOM::HTML;
-use Scalar::Util qw(blessed weaken);
+use Scalar::Util 'weaken';
 
 sub all_text { _text(_nodes(shift->tree), 1) }
 
@@ -178,6 +178,8 @@
   return exists $self->{multiple} ? $v->size ? $v->to_array : undef : $v->last;
 }
 
+sub with_roles { shift->Mojo::Base::with_roles(@_) }
+
 sub wrap         { shift->_wrap(0, @_) }
 sub wrap_content { shift->_wrap(1, @_) }
 
@@ -946,6 +948,13 @@
   # "on"
   $dom->parse('<input name=test type=checkbox>')->at('input')->val;
 
+=head2 with_roles
+
+  my $new_class = Mojo::DOM->with_roles('Mojo::DOM::Role::One');
+  my $new_class = Mojo::DOM->with_roles('+One', '+Two');
+
+Alias for L<Mojo::Base/"with_roles">.
+
 =head2 wrap
 
   $dom = $dom->wrap('<div></div>');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/File.pm 
new/Mojolicious-7.42/lib/Mojo/File.pm
--- old/Mojolicious-7.39/lib/Mojo/File.pm       2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/File.pm       2017-08-16 23:41:49.000000000 
+0200
@@ -137,6 +137,8 @@
 
 sub to_string {"${$_[0]}"}
 
+sub with_roles { shift->Mojo::Base::with_roles(@_) }
+
 1;
 
 =encoding utf8
@@ -446,6 +448,13 @@
 
 Stringify the path.
 
+=head2 with_roles
+
+  my $new_class = Mojo::File->with_roles('Mojo::File::Role::One');
+  my $new_class = Mojo::File->with_roles('+One', '+Two');
+
+Alias for L<Mojo::Base/"with_roles">.
+
 =head1 OPERATORS
 
 L<Mojo::File> overloads the following operators.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojo/Log.pm 
new/Mojolicious-7.42/lib/Mojo/Log.pm
--- old/Mojolicious-7.39/lib/Mojo/Log.pm        2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojo/Log.pm        2017-08-14 10:12:20.000000000 
+0200
@@ -19,8 +19,7 @@
 has level => 'debug';
 has max_history_size => 10;
 has 'path';
-has short =>
-  sub { $ENV{INVOCATION_ID} && $ENV{JOURNAL_STREAM} && !shift->path };
+has short => sub { $ENV{MOJO_LOG_SHORT} };
 
 # Supported log levels
 my %LEVEL = (debug => 1, info => 2, warn => 3, error => 4, fatal => 5);
@@ -178,8 +177,7 @@
   $log     = $log->short($bool);
 
 Generate short log messages without a timestamp, suitable for systemd, defaults
-to auto-detection based on the presence of a L</"path"> and the
-C<INVOCATION_ID> and C<JOURNAL_STREAM> environment variables.
+to the value of the C<MOJO_LOG_SHORT> environment variables.
 
 =head1 METHODS
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Command/version.pm 
new/Mojolicious-7.42/lib/Mojolicious/Command/version.pm
--- old/Mojolicious-7.39/lib/Mojolicious/Command/version.pm     2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Command/version.pm     2017-08-11 
10:27:26.000000000 +0200
@@ -11,11 +11,12 @@
 sub run {
   my $self = shift;
 
-  my $ev = eval 'use Mojo::Reactor::EV; 1' ? $EV::VERSION : 'n/a';
+  my $ev = eval { require Mojo::Reactor::EV; 1 } ? $EV::VERSION : 'n/a';
   my $socks
     = Mojo::IOLoop::Client->can_socks ? $IO::Socket::Socks::VERSION : 'n/a';
   my $tls = Mojo::IOLoop::TLS->can_tls    ? $IO::Socket::SSL::VERSION  : 'n/a';
   my $nnr = Mojo::IOLoop::Client->can_nnr ? $Net::DNS::Native::VERSION : 'n/a';
+  my $roles = Mojo::Base->ROLES ? $Role::Tiny::VERSION : 'n/a';
 
   print <<EOF;
 CORE
@@ -27,6 +28,7 @@
   IO::Socket::Socks 0.64+ ($socks)
   IO::Socket::SSL 1.94+   ($tls)
   Net::DNS::Native 0.15+  ($nnr)
+  Role::Tiny 2.000001+    ($roles)
 
 EOF
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Mojolicious-7.39/lib/Mojolicious/Guides/Contributing.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Contributing.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Contributing.pod        
2017-07-18 18:47:28.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Contributing.pod        
2017-08-12 00:41:04.000000000 +0200
@@ -303,8 +303,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/Cookbook.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Cookbook.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Cookbook.pod    2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Cookbook.pod    2017-08-12 
00:40:53.000000000 +0200
@@ -795,36 +795,6 @@
 You can also use L<Mojo::Transaction::WebSocket/"with_protocols"> to negotiate 
a
 subprotocol.
 
-=head2 Testing WebSocket web services
-
-While the message flow on WebSocket connections can be rather dynamic, it more
-often than not is quite predictable, which allows this rather pleasant
-L<Test::Mojo> API to be used.
-
-  use Test::More;
-  use Test::Mojo;
-
-  # Include application
-  use FindBin;
-  require "$FindBin::Bin/../echo.pl";
-
-  # Test echo web service
-  my $t = Test::Mojo->new;
-  $t->websocket_ok('/echo')
-    ->send_ok('Hello Mojo!')
-    ->message_ok
-    ->message_is('echo: Hello Mojo!')
-    ->finish_ok;
-
-  # Test JSON web service
-  $t->websocket_ok('/echo.json')
-    ->send_ok({json => {test => [1, 2, 3]}})
-    ->message_ok
-    ->json_message_is('/test', [1, 2, 3])
-    ->finish_ok;
-
-  done_testing();
-
 =head2 EventSource web service
 
 EventSource is a special form of long polling where you can use
@@ -1779,8 +1749,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/FAQ.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/FAQ.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/FAQ.pod 2017-07-21 
18:10:18.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/FAQ.pod 2017-08-12 
00:40:40.000000000 +0200
@@ -35,7 +35,8 @@
 discourage adding non-optional ones in favor of a faster and more painless
 installation process. And we do in fact already use several optional CPAN
 modules such as L<EV>, L<IO::Socket::Socks>, L<IO::Socket::SSL>,
-L<Net::DNS::Native> and L<Plack> to provide advanced functionality if possible.
+L<Net::DNS::Native>, L<Plack> and L<Role::Tiny> to provide advanced
+functionality if possible.
 
 =head2 Why reinvent wheels?
 
@@ -236,8 +237,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/Growing.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Growing.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Growing.pod     2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Growing.pod     2017-08-12 
00:40:32.000000000 +0200
@@ -816,8 +816,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Mojolicious-7.39/lib/Mojolicious/Guides/Rendering.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Rendering.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Rendering.pod   2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Rendering.pod   2017-08-12 
00:40:24.000000000 +0200
@@ -1501,8 +1501,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/Routing.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Routing.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Routing.pod     2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Routing.pod     2017-08-12 
00:40:03.000000000 +0200
@@ -1069,8 +1069,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/Testing.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Testing.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Testing.pod     1970-01-01 
01:00:00.000000000 +0100
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Testing.pod     2017-08-16 
23:53:50.000000000 +0200
@@ -0,0 +1,718 @@
+
+=encoding utf8
+
+=head1 NAME
+
+Mojolicious::Guides::Testing - Web Application Testing Made Easy
+
+=head1 OVERVIEW
+
+This document is an introduction to testing web applications with 
L<Test::Mojo>.
+L<Test::Mojo> can be thought of as a module that provides all of the tools and
+testing assertions needed to test web applications in a Perl-ish way.
+
+While L<Test::Mojo> can be used to test any web application, it has shortcuts
+designed to make testing L<Mojolicious> web applications easy and pain-free.
+
+Please refer to the L<Test::Mojo> documentation for a complete reference to 
many
+of the ideas and syntax introduced in this document.
+
+A test file for a simple web application might look like:
+
+  use Mojo::Base -strict;
+
+  use Test::Mojo;
+  use Test::More;
+
+  # Start a Mojolicious app named "Celestial"
+  my $t = Test::Mojo->new('Celestial');
+
+  # Post a JSON document
+  $t->post_ok('/notifications' => json => {event => 'full moon'})
+    ->status_is(201)
+    ->json_is('/message' => 'notification created');
+
+  # Perform GET requests and look at the responses
+  $t->get_ok('/sunrise')
+    ->status_is(200)
+    ->content_like(qr/ am$/);
+  $t->get_ok('/sunset')
+    ->status_is(200)
+    ->content_like(qr/ pm$/);
+
+  # Post a URL-encoded form
+  $t->post_ok('/insurance' => form => {name => 'Jimmy', amount => 
'€3.000.000'})
+    ->status_is(200);
+
+  # Use Test::More's like() to check the response
+  like $t->tx->res->dom->at('div#thanks')->text, qr/thank you/, 'thanks';
+
+  done_testing();
+
+In the rest of this document we'll explore these concepts and others related to
+L<Test::Mojo>.
+
+=head1 CONCEPTS
+
+Essentials every L<Mojolicious> developer should know.
+
+=head2 L<Test::Mojo> at a glance
+
+The L<Test::More> module bundled with Perl includes several primitive test
+assertions, such as C<ok>, C<is>, C<isnt>, C<like>, C<unlike>, C<cmp_ok>, etc.
+An assertion "passes" if its expression returns a true value. The assertion
+method prints "ok" or "not ok" if an assertion passes or fails (respectively).
+
+L<Test::Mojo> supplies additional test assertions organized around the web
+application request/response transaction (transport, response headers, response
+bodies, etc.), and WebSocket communications.
+
+One interesting thing of note: the return value of L<Test::Mojo> object
+assertions is always the test object itself, allowing us to "chain" test
+assertion methods. So rather than grouping related test statements like this:
+
+  $t->get_ok('/frogs');
+  $t->status_is(200);
+  $t->content_like(qr/bullfrog/);
+  $t->content_like(qr/hypnotoad/);
+
+Method chaining allows us to connect test assertions that belong together:
+
+  $t->get_ok('/frogs')
+    ->status_is(200)
+    ->content_like(qr/bullfrog/)
+    ->content_like(qr/hypnotoad/);
+
+This makes for a much more I<concise> and I<coherent> testing experience:
+concise because we are not repeating the invocant for each test, and coherent
+because assertions that belong to the same request are syntactically bound in
+the same method chain.
+
+Occasionally it makes sense to break up a test to perform more complex
+assertions on a response. L<Test::Mojo> exposes the entire transaction object 
so
+you can get all the data you need from a response:
+
+  $t->put_ok('/bees' => json => {type => 'worker', name => 'Karl'})
+    ->status_is(202)
+    ->json_has('/id');
+
+  # Pull out the id from the response
+  my $newbee = $t->tx->res->json('/id');
+
+  # Make a new request with data from the previous response
+  $t->get_ok("/bees/$newbee")
+    ->status_is(200)
+    ->json_is('/name' => 'Karl');
+
+The L<Test::Mojo> object is I<stateful>. As long as we haven't started a new
+transaction by invoking one of the C<*_ok> methods, the request and response
+objects from the previous transaction are available in the L<Test::Mojo>
+object:
+
+  # First transaction
+  $t->get_ok('/frogs?q=bullfrog' => {'Content-Type' => 'application/json'})
+    ->status_is(200)
+    ->json_like('/0/species' => qr/catesbeianus/i);
+
+  # Still first transaction
+  $t->content_type_is('application/json');
+
+  # Second transaction
+  $t->get_ok('/frogs?q=banjo' => {'Content-Type' => 'text/html'})
+    ->status_is(200)
+    ->content_like(qr/interioris/i);
+
+  # Still second transaction
+  $t->content_type_is('text/html');
+
+This statefulness also enables L<Test::Mojo> to handle sessions, follow
+redirects, and inspect past responses during a redirect.
+
+=head2 The L<Test::Mojo> object
+
+The L<Test::Mojo> object manages the Mojolicious application lifecycle (if a
+Mojolicious application class is supplied) as well as exposes the built-in
+L<Mojo::UserAgent> object. To create a bare L<Test::Mojo> object:
+
+  my $t = Test::Mojo->new;
+
+This object initializes a L<Mojo::UserAgent> object and provides a variety of
+test assertion methods for accessing a web application. For example, with this
+object, we could test any running web application:
+
+  $t->get_ok('https://www.google.com/')
+    ->status_is(200)
+    ->content_like(qr/search/i);
+
+You can access the user agent directly if you want to make web requests without
+triggering test assertions:
+
+  my $tx = $t->ua->post(
+    'https://duckduckgo.com/html' => form => {q => 'hypnotoad'});
+  $tx->result->dom->find('a.result__a')->each(sub { say $_->text });
+
+See L<Mojo::UserAgent> for the complete API and return values.
+
+=head2 Testing Mojolicious applications
+
+If you pass the name of a L<Mojolicious> application class (e.g., 'MyApp') to
+the L<Test::Mojo> constructor, L<Test::Mojo> will instantiate the class and
+start it, and cause it to listen on a random (unused) port number. Testing a
+Mojolicious application using L<Test::Mojo> will never conflict with running
+applications, including the application you're testing.
+
+The L<Mojo::UserAgent> object in L<Test::Mojo> will know where the application
+is running and make requests to it. Once the tests have completed, the
+L<Mojolicious> application will be torn down.
+
+  # Listens on localhost:32114 (some unused TCP port)
+  my $t = Test::Mojo->new('Frogs');
+
+This object initializes a L<Mojo::UserAgent> object, loads the Mojolicious
+application C<Frogs>, binds and listens on a free TCP port (e.g., 32114), and
+starts the application event loop. When the L<Test::Mojo> object (C<$t>) goes
+out of scope, the application is stopped.
+
+Relative URLs in the test object method assertions (C<get_ok>, C<post_ok>, 
etc.)
+will be sent to the Mojolicious application started by L<Test::Mojo>:
+
+  # Rewritten to "http://localhost:32114/frogs";
+  $t->get_ok('/frogs');
+
+L<Test::Mojo> has a lot of handy shortcuts built into it to make testing
+L<Mojolicious> or L<Mojolicious::Lite> applications enjoyable.
+
+=head3 An example
+
+Let's spin up a Mojolicious application using C<mojo generate app MyApp>. The
+C<mojo> utility will create a working application and a C<t> directory with a
+working test file:
+
+  $ mojo generate app MyApp
+  [mkdir] /my_app/script
+  [write] /my_app/script/my_app
+  [chmod] /my_app/script/my_app 744
+  ...
+  [mkdir] /my_app/t
+  [write] /my_app/t/basic.t
+  ...
+
+Let's run the tests (we'll create the C<log> directory to quiet the application
+output):
+
+  $ cd my_app
+  $ mkdir log
+  $ prove -lv t
+  t/basic.t ..
+  ok 1 - GET /
+  ok 2 - 200 OK
+  ok 3 - content is similar
+  1..3
+  ok
+  All tests successful.
+  Files=1, Tests=3,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.33 cusr  0.07
+   csys =  0.44 CPU)
+  Result: PASS
+
+The boilerplate test file looks like this:
+
+  use Mojo::Base -strict;
+
+  use Test::More;
+  use Test::Mojo;
+
+  my $t = Test::Mojo->new('MyApp');
+  $t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i);
+
+  done_testing();
+
+Here we can see our application class name C<MyApp> is passed to the
+L<Test::Mojo> constructor. Under the hood, L<Test::Mojo> creates a new
+L<Mojo::Server> instance, loads C<MyApp> (which we just created), and runs the
+application. We write our tests with relative URLs because L<Test::Mojo> takes
+care of getting the request to the running test application (since its port may
+change between runs).
+
+=head3 Testing with configuration data
+
+We can alter the behavior of our application using environment variables (such
+as C<MOJO_MODE>) and through configuration values. One nice feature of
+L<Test::Mojo> is its ability to pass configuration values directly from its
+constructor.
+
+Let's modify our application and add a "feature flag" to enable a new feature
+when the C<enable_weather> configuration value is set:
+
+  # Load configuration from hash returned by "my_app.conf"
+  my $config = $self->plugin('Config');
+
+  # Normal route to controller
+  $r->get('/')->to('example#welcome');
+
+  # NEW: this route only exists if "enable_weather" is set in the configuration
+  if ($config->{enable_weather}) {
+    $r->get('/weather' => sub { shift->render(text => "It's hot! 🔥") }
+  }
+
+To test this new feature, we don't even need to create a configuration file—we
+can simply pass the configuration data to the application directly via
+L<Test::Mojo>'s constructor:
+
+  my $t = Test::Mojo->new(MyApp => {enable_weather => 1});
+  $t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i);
+  $t->get_ok('/weather')->status_is(200)->content_like(qr/🔥/);
+
+When we run these tests, L<Test::Mojo> will pass this configuration data to the
+application, which will cause it to create a special C</weather> route that we
+can access in our tests. Unless C<enable_weather> is set in a configuration
+file, this route will not exist when the application runs. Feature flags like
+this allow us to do soft rollouts of features, targeting a small audience for a
+period of time. Once the feature has been proven, we can refactor the
+conditional and make it a full release.
+
+This example shows how easy it is to start testing a Mojolicious application 
and
+how to set specific application configuration directives from a test file.
+
+=head3 Testing application helpers
+
+Let's say we register a helper in our application to generate an HTTP Basic
+Authorization header:
+
+  use Mojo::Util 'b64_encode';
+
+  app->helper(basic_auth => sub {
+    my ($c, @values) = @_;
+    return {Authorization => 'Basic ' . b64_encode join(':' => @values), ''};
+  });
+
+How do we test application helpers like this? L<Test::Mojo> has access to the
+application object, which allows us to invoke helpers from our test file:
+
+  my $t = Test::Mojo->new('MyApp');
+
+  is_deeply $t->app->basic_auth(bif => "Bif's Passwerdd"),
+    {Authorization => 'Basic YmlmOkJpZidzIFBhc3N3ZXJkZA=='},
+    'correct header value';
+
+Any aspect of the application (helpers, plugins, routes, etc.) can be
+introspected from L<Test::Mojo> through the application object. This enables us
+to get deep test coverage of L<Mojolicious>-based applications.
+
+=head1 ASSERTIONS
+
+This section describes the basic test assertions supplied by L<Test::Mojo>.
+There are four broad categories of assertions for HTTP requests:
+
+=over 2
+
+=item * HTTP requests
+
+=item * HTTP response status
+
+=item * HTTP response headers
+
+=item * HTTP response content/body
+
+=back
+
+WebSocket test assertions are covered in L</Testing WebSocket web services>.
+
+=head2 HTTP request assertions
+
+L<Test::Mojo> has a L<Mojo::UserAgent> object that allows it to make HTTP
+requests and check for HTTP transport errors. HTTP request assertions include
+C<get_ok>, C<post_ok>, etc. These assertions do not test whether the request
+was handled I<successfully>, only that the web application handled the request
+in an HTTP compliant way.
+
+You may also make HTTP requests using custom verbs (beyond C<GET>, C<POST>,
+C<PUT>, etc.) by building your own transaction object. See
+L</"Custom transactions"> below.
+
+=head3 Using HTTP request assertions
+
+To post a URL-encoded form to the C</calls> endpoint of an application, we
+simply use the C<form> content type shortcut:
+
+  $t->post_ok('/calls' => form => {to => '+43.55.555.5555'});
+
+Which will create the following HTTP request:
+
+  POST /calls HTTP/1.1
+  Content-Length: 20
+  Content-Type: application/x-www-form-urlencoded
+
+  to=%2B43.55.555.5555
+
+The C<*_ok> HTTP request assertion methods accept the same arguments as their
+corresponding L<Mojo::UserAgent> methods (except for the callback argument).
+This allows us to set headers and build query strings for authentic test
+situations:
+
+  $t->get_ok('/internal/personnel' => {Authorization => 'Token 
secret-password'}
+    => form => {q => 'Professor Plum'});
+
+which generates the following request:
+
+  GET /internal/personnel?q=Professor+Plum HTTP/1.1
+  Content-Length: 0
+  Authorization: Token secret-password
+
+The C<form> content generator (see L<Mojo::UserAgent::Transactor>) will 
generate
+a query string for C<GET> requests and C<application/x-www-form-urlencoded> or
+C<multipart/form-data> for POST requests.
+
+While these C<*_ok> assertions make the HTTP I<requests> we expect, they tell 
us
+little about I<how well> the application handled the request. The application
+we're testing might have returned any content-type, body, or HTTP status code
+(200, 302, 400, 404, 500, etc.) and we wouldn't know it.
+
+L<Test::Mojo> provides assertions to test almost every aspect of the HTTP
+response, including the HTTP response status code, the value of the
+C<Content-Type> header, and other arbitrary HTTP header information.
+
+=head2 HTTP response status code
+
+While not technically an HTTP header, the status line is the first line in an
+HTTP response and is followed by the response headers. Testing the response
+status code is common in REST-based and other web applications that use the 
HTTP
+status codes to broadly indicate the type of response the server is returning.
+
+Testing the status code is as simple as adding the C<status_is> assertion:
+
+  $t->post_ok('/doorbell' => form => {action => 'ring once'})
+    ->status_is(200);
+
+Along with C<status_isnt>, this will cover most needs. For more elaborate 
status
+code testing, you can access the response internals directly:
+
+  $t->post_ok('/doorbell' => form => {action => 'ring once'});
+  is $t->tx->res->message, 'Moved Permanently', 'try next door';
+
+=head2 HTTP response headers
+
+L<Test::Mojo> allows us to inspect and make assertions about HTTP response
+headers. The C<Content-Type> header is commonly tested and has its own
+assertion:
+
+  $t->get_ok('/map-of-the-world.pdf')
+    ->content_type_is('application/pdf');
+
+This is equivalent to the more verbose:
+
+  $t->get_ok('/map-of-the-world.pdf')
+    ->header_is('Content-Type' => 'application/pdf');
+
+We can test for multiple headers in a single response using method chains:
+
+  $t->get_ok('/map-of-the-world.pdf')
+    ->content_type_is('application/pdf')
+    ->header_isnt('Compression' => 'gzip')
+    ->header_unlike('Server' => qr/IIS/i);
+
+=head2 HTTP response content assertions
+
+L<Test::Mojo> also exposes a rich set of assertions for testing the body of a
+response, whether that body be HTML, plain-text, or JSON. The C<content_*>
+methods look at the body of the response as plain text (as defined by the
+response's character set):
+
+  $t->get_ok('/scary-things/spiders.json')
+    ->content_is('{"arachnid":"brown recluse"}');
+
+Although this is a JSON document, C<content_is> treats it as if it were a text
+document. This may be useful for situations where we're looking for a 
particular
+string and not concerned with the structure of the document. For example, we 
can
+do the same thing with an HTML document:
+
+  $t->get_ok('/scary-things/spiders.html')
+    ->content_like(qr{<title>All The Spiders</title>});
+
+But because L<Test::Mojo> has access to everything that L<Mojo::UserAgent> 
does,
+we can introspect JSON documents as well as DOM-based documents (HTML, XML) 
with
+assertions that allow us to check for the existence of elements as well as
+inspect the content of text nodes.
+
+=head3 JSON response assertions
+
+L<Test::Mojo>'s L<Mojo::UserAgent> has access to a JSON parser, which allows us
+to test to see if a JSON response contains a value at a location in the 
document
+using JSON pointer syntax:
+
+  $t->get_ok('/animals/friendly.json')
+    ->json_has('/beings/jeremiah/age');
+
+This assertion tells us that the C<friendly.json> document contains a value at
+the C</beings/jeremiah/age> JSON pointer location. We can also inspect the 
value
+at JSON pointer locations:
+
+  $t->get_ok('/animals/friendly.json')
+    ->json_has('/beings/jeremiah/age')
+    ->json_is('/beings/jeremiah/age' => 42)
+    ->json_like('/beings/jeremiah/species' => qr/bullfrog/i);
+
+JSON pointer syntax makes testing JSON responses simple and readable.
+
+=head3 DOM response assertions
+
+We can also inspect HTML and XML responses using the L<Mojo::DOM> parser in the
+user agent. Here are a few examples from the L<Test::Mojo> documentation:
+
+  $t->text_is('div.foo[x=y]' => 'Hello!');
+  $t->text_is('html head title' => 'Hello!', 'right title');
+
+The L<Mojo::DOM> parser uses the CSS selector syntax described in
+L<Mojo::DOM::CSS>, allowing us to test for values in HTML and XML documents
+without resorting to typically verbose and inflexible DOM traversal methods.
+
+=head1 ADVANCED TOPICS
+
+This section describes some complex (but common) testing situations that
+L<Test::Mojo> excels in making simple.
+
+=head2 Redirects
+
+The L<Mojo::UserAgent> object in L<Test::Mojo> can handle HTTP redirections
+internally to whatever level you need. Let's say we have a web service that
+redirects C</1> to C</2>, C</2> redirects to C</3>, C</3> redirects to C</4>,
+and C</4> redirects to C</5>:
+
+  GET /1
+
+returns:
+
+  302 Found
+  Location: /2
+
+and:
+
+  GET /2
+
+returns:
+
+  302 Found
+  Location: /3
+
+and so forth, up to C</5>:
+
+  GET /5
+
+which returns the data we wanted:
+
+  200 OK
+
+  {"message":"this is five"}
+
+We can tell the user agent in L<Test::Mojo> how to deal with redirects. Each
+test is making a request to C<GET /1>, but we vary the number of redirects the
+user agent should follow with each test:
+
+  my $t = Test::Mojo->new;
+
+  $t->get_ok('/1')
+    ->header_is(location => '/2');
+
+  $t->ua->max_redirects(1);
+  $t->get_ok('/1')
+    ->header_is(location => '/3');
+
+  $t->ua->max_redirects(2);
+  $t->get_ok('/1')
+    ->header_is(location => '/4');
+
+  # Look at the previous hop
+  is $t->tx->previous->res->headers->location, '/3', 'previous redirect';
+
+  $t->ua->max_redirects(3);
+  $t->get_ok('/1')
+    ->header_is(location => '/5');
+
+  $t->ua->max_redirects(4);
+  $t->get_ok('/1')
+    ->json_is('/message' => 'this is five');
+
+When we set C<max_redirects>, it stays set for the life of the test object 
until
+we change it.
+
+L<Test::Mojo>'s handling of HTTP redirects eliminates the need for making many,
+sometimes an unknown number, of redirections to keep testing precise and easy 
to
+follow (ahem).
+
+=head2 Cookies and session management
+
+We can use L<Test::Mojo> to test applications that keep session state in
+cookies. By default, the L<Mojo::UserAgent> object in L<Test::Mojo> will manage
+session for us by saving and sending cookies automatically, just like common 
web
+browsers:
+
+  use Mojo::Base -strict;
+
+  use Test::More;
+  use Test::Mojo;
+
+  my $t = Test::Mojo->new('MyApp');
+
+  # No authorization cookie
+  $t->get_ok('/')
+    ->status_is(401)
+    ->content_is('Please log in');
+
+  # Application sets an authorization cookie
+  $t->post_ok('/login' => form => {password => 'let me in'})
+    ->status_is(200)
+    ->content_is('You are logged in');
+
+  # Sends the cookie from the previous transaction
+  $t->get_ok('/')
+    ->status_is(200)
+    ->content_like(qr/You logged in at \d+/);
+
+  # Clear the cookies
+  $t->reset_session;
+
+  # No authorization cookie again
+  $t->get_ok('/')
+    ->status_is(401)
+    ->content_is('Please log in');
+
+We can also inspect cookies in responses for special values through the
+transaction's response (L<Mojo::Message::Response>) object:
+
+  $t->get_ok('/');
+  like $t->tx->res->cookie('smarty'), qr/smarty=pants/, 'cookie found';
+
+=head2 Custom transactions
+
+Let's say we have an application that responds to a new HTTP verb C<RING> and 
to
+use it we must also pass in a secret cookie value. This is not a problem. We 
can
+test the application by creating a L<Mojo::Transaction> object, setting the
+cookie (see L<Mojo::Message::Request>), then passing the transaction object to
+C<request_ok>:
+
+  # Use custom "RING" verb
+  my $tx = $t->ua->build_tx(RING => '/doorbell');
+
+  # Set a special cookie
+  $tx->req->cookies({name => 'Secret', value => "don't tell anybody"});
+
+  # Make the request
+  $t->request_ok($tx)
+    ->status_is(200)
+    ->json_is('/status' => 'ding dong');
+
+=head2 Testing WebSocket web services
+
+While the message flow on WebSocket connections can be rather dynamic, it more
+often than not is quite predictable, which allows this rather pleasant
+L<Test::Mojo> WebSocket API to be used:
+
+  use Mojo::Base -strict;
+
+  use Test::More;
+  use Test::Mojo;
+
+  # Test echo web service
+  my $t = Test::Mojo->new('EchoService');
+  $t->websocket_ok('/echo')
+    ->send_ok('Hello Mojo!')
+    ->message_ok
+    ->message_is('echo: Hello Mojo!')
+    ->finish_ok;
+
+  # Test JSON web service
+  $t->websocket_ok('/echo.json')
+    ->send_ok({json => {test => [1, 2, 3]}})
+    ->message_ok
+    ->json_message_is('/test' => [1, 2, 3])
+    ->finish_ok;
+
+  done_testing();
+
+Because of their inherent asynchronous nature, testing WebSocket communications
+can be tricky. The L<Test::Mojo> WebSocket assertions serialize messages via
+event loop primitives. This enables us to treat WebSocket messages as if they
+were using the same request-response communication pattern we're accustomed to
+with HTTP.
+
+To illustrate, let's walk through these tests. In the first test, we use the
+C<websocket_ok> assertion to ensure that we can connect to our application's
+WebSocket route at C</echo> and that it's "speaking" WebSocket protocol to us.
+The next C<send_ok> assertion tests the connection again (in case it closed, 
for
+example) and attempts to send the message C<Hello Mojo!>. The next assertion,
+C<message_ok>, blocks (using the L<Mojo::IOLoop> singleton in the application)
+and waits for a response from the server. The response is then compared with
+C<'echo: Hello Mojo!'> in the C<message_is> assertion, and finally we close and
+test our connection status again with C<finish_ok>.
+
+The second test is like the first, but now we're sending and expecting JSON
+documents at C</echo.json>. In the C<send_ok> assertion we take advantage of
+L<Mojo::UserAgent>'s JSON content generator (see 
L<Mojo::UserAgent::Transactor>)
+to marshal hash and array references into JSON documents, and then send them as
+a WebSocket message. We wait (block) for a response from the server with
+C<message_ok>. Then because we're expecting a JSON document back, we can
+leverage C<json_message_ok> which parses the WebSocket response body and 
returns
+an object we can access through L<Mojo::JSON::Pointer> syntax. Then we close
+(and test) our WebSocket connection.
+
+Testing WebSocket servers does not get any simpler than with L<Test::Mojo>.
+
+=head2 Extending L<Test::Mojo>
+
+If you see that you're writing a lot of test assertions that aren't chainable,
+you may benefit from writing your own test assertions. Let's say we want to 
test
+the C<Location> header after a redirect. We'll create a new class with
+L<Role::Tiny> that implements a test assertion named C<location_is>:
+
+  package Test::Mojo::Role::Location;
+
+  use Role::Tiny;
+  use Test::More;
+
+  sub location_is {
+    my ($t, $value, $desc) = @_;
+    $desc ||= "Location: $value";
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+    return $t->success(is($t->tx->res->headers->location, $value, $desc));
+  }
+
+  1;
+
+When we make new test assertions using roles, we want to use method signatures
+that match other C<*_is> methods in L<Test::Mojo>, so here we accept the test
+object, the value to compare, and an optional description.
+
+We assign a default description value (C<$desc>), set the L<Test::Builder>
+C<Level> global variable one level higher (which tells L<Test::Builder> how far
+up the call stack to look when something fails), then we use L<Test::More>'s
+C<is> function to compare the location header with the expected header value. 
We
+wrap that in the C<success> attribute, which records the boolean test result 
and
+propagates the L<Test::Mojo> object for method chaining.
+
+With this new package, we're ready to compose a new test object that uses the
+role:
+
+  my $t = Test::Mojo->with_roles('+Location')->new('MyApp');
+
+  $t->post_ok('/redirect/mojo' => json => {message => 'Mojo, here I come!'})
+    ->status_is(302)
+    ->location_is('http://mojolicious.org')
+    ->or(sub { diag 'I miss tempire.' });
+
+In this section we've covered how to add custom test assertions to 
L<Test::Mojo>
+with roles and how to use those roles to simplify testing.
+
+=head1 MORE
+
+You can continue with L<Mojolicious::Guides> now or take a look at the
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
+
+=head1 SUPPORT
+
+If you have any questions the documentation might not yet answer, don't
+hesitate to ask on the
+L<mailing list|http://groups.google.com/group/mojolicious> or the official IRC
+channel C<#mojo> on C<irc.perl.org>
+(L<chat now!|https://chat.mibbit.com/?channel=%23mojo&server=irc.perl.org>).
+
+=cut
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides/Tutorial.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides/Tutorial.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides/Tutorial.pod    2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides/Tutorial.pod    2017-08-12 
00:40:16.000000000 +0200
@@ -996,8 +996,8 @@
 =head1 MORE
 
 You can continue with L<Mojolicious::Guides> now or take a look at the
-L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot
-more documentation and examples by many different authors.
+L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot 
more
+documentation and examples by many different authors.
 
 =head1 SUPPORT
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious/Guides.pod 
new/Mojolicious-7.42/lib/Mojolicious/Guides.pod
--- old/Mojolicious-7.39/lib/Mojolicious/Guides.pod     2017-07-17 
21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/lib/Mojolicious/Guides.pod     2017-08-12 
00:12:40.000000000 +0200
@@ -88,6 +88,11 @@
 
 Generating content with the L<Mojolicious> renderer.
 
+=item L<Mojolicious::Guides::Testing>
+
+Powerful yet elegant testing techniques and tools for L<Mojolicious> and other
+web applications.
+
 =item L<Mojolicious::Guides::Cookbook>
 
 Cooking with L<Mojolicious>, recipes for every taste.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Mojolicious.pm 
new/Mojolicious-7.42/lib/Mojolicious.pm
--- old/Mojolicious-7.39/lib/Mojolicious.pm     2017-08-02 12:09:15.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Mojolicious.pm     2017-08-16 10:19:34.000000000 
+0200
@@ -58,7 +58,7 @@
 has validator => sub { Mojolicious::Validator->new };
 
 our $CODENAME = 'Doughnut';
-our $VERSION  = '7.39';
+our $VERSION  = '7.42';
 
 sub AUTOLOAD {
   my $self = shift;
@@ -909,6 +909,8 @@
 
 Dominique Dumont
 
+Dotan Dimet
+
 Douglas Christopher Wilson
 
 Eugen Konkov
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/lib/Test/Mojo.pm 
new/Mojolicious-7.42/lib/Test/Mojo.pm
--- old/Mojolicious-7.39/lib/Test/Mojo.pm       2017-07-17 21:07:54.000000000 
+0200
+++ new/Mojolicious-7.42/lib/Test/Mojo.pm       2017-08-12 00:12:28.000000000 
+0200
@@ -450,6 +450,8 @@
 be set to C<debug> or C<fatal>, depending on the value of the
 C<HARNESS_IS_VERBOSE> environment variable.
 
+See L<Mojolicious::Guides::Testing> for more.
+
 =head1 ATTRIBUTES
 
 L<Test::Mojo> implements the following attributes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/t/mojo/log.t 
new/Mojolicious-7.42/t/mojo/log.t
--- old/Mojolicious-7.39/t/mojo/log.t   2017-07-17 21:07:54.000000000 +0200
+++ new/Mojolicious-7.42/t/mojo/log.t   2017-08-14 10:11:31.000000000 +0200
@@ -50,22 +50,19 @@
 like $log->format->(time, 'debug', qw(Test 1 2 3)), qr/^debug:\d+:Test:1:2:3$/,
   'right format';
 
-# systemd
+# Short log messages
 {
   $log = Mojo::Log->new;
-  ok !$log->short, 'systemd has not been detected';
+  ok !$log->short, 'long messages';
   like $log->format->(time, 'debug', 'Test 123'),
     qr/^\[.*\] \[debug\] Test 123\n$/, 'right format';
-  local $ENV{JOURNAL_STREAM} = '1:23456';
-  local $ENV{INVOCATION_ID}  = 1;
+  local $ENV{MOJO_LOG_SHORT} = 1;
   $log = Mojo::Log->new;
-  ok $log->short, 'systemd has been detected';
+  ok $log->short, 'short messages';
+  $log = Mojo::Log->new(short => 1);
+  ok $log->short, 'short messages';
   like $log->format->(time, 'debug', 'Test 123'), qr/^\[debug\] Test 123\n$/,
     'right format';
-  $log = Mojo::Log->new(path => $path);
-  ok !$log->short, 'a path will be used';
-  like $log->format->(time, 'debug', 'Test 123'),
-    qr/^\[.*\] \[debug\] Test 123\n$/, 'right format';
 }
 
 # Events
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.39/t/mojo/roles.t 
new/Mojolicious-7.42/t/mojo/roles.t
--- old/Mojolicious-7.39/t/mojo/roles.t 1970-01-01 01:00:00.000000000 +0100
+++ new/Mojolicious-7.42/t/mojo/roles.t 2017-08-16 23:42:31.000000000 +0200
@@ -0,0 +1,100 @@
+use Mojo::Base -strict;
+
+use Test::More;
+
+BEGIN {
+  plan skip_all => 'Role::Tiny 2.000001+ required for this test!'
+    unless Mojo::Base->ROLES;
+}
+
+package Mojo::RoleTest::Role::LOUD;
+use Role::Tiny;
+
+sub yell {'HEY!'}
+
+requires 'name';
+
+sub hello {
+  my $self = shift;
+  return $self->yell . ' ' . uc($self->name) . '!!!';
+}
+
+package Mojo::RoleTest::Role::quiet;
+use Role::Tiny;
+
+requires 'name';
+
+sub whisper {
+  my $self = shift;
+  return 'psst, ' . lc($self->name);
+}
+
+package Mojo::RoleTest;
+use Mojo::Base -base;
+
+has name => 'bob';
+
+sub hello {
+  my ($self) = shift;
+  return 'hello ' . $self->name;
+}
+
+package Mojo::RoleTest::Hello;
+use Role::Tiny;
+
+sub hello {'hello mojo!'}
+
+package main;
+
+use Mojo::ByteStream;
+use Mojo::Collection;
+use Mojo::DOM;
+use Mojo::File;
+
+# Plain class
+my $obj = Mojo::RoleTest->new(name => 'Ted');
+is $obj->name,  'Ted',       'attribute';
+is $obj->hello, 'hello Ted', 'method';
+
+# Single role
+my $obj2 = Mojo::RoleTest->with_roles('Mojo::RoleTest::Role::LOUD')->new;
+is $obj2->hello, 'HEY! BOB!!!', 'role method';
+is $obj2->yell,  'HEY!',        'another role method';
+
+# Single role (shorthand)
+my $obj4 = Mojo::RoleTest->with_roles('+LOUD')->new;
+is $obj4->hello, 'HEY! BOB!!!', 'role method';
+is $obj4->yell,  'HEY!',        'another role method';
+
+# Multiple roles
+my $obj3 = Mojo::RoleTest->with_roles('Mojo::RoleTest::Role::quiet',
+  'Mojo::RoleTest::Role::LOUD')->new(name => 'Joel');
+is $obj3->name,    'Joel',         'base attribute';
+is $obj3->whisper, 'psst, joel',   'method from first role';
+is $obj3->hello,   'HEY! JOEL!!!', 'method from second role';
+
+# Multiple roles (shorthand)
+my $obj5 = Mojo::RoleTest->with_roles('+quiet', '+LOUD')->new(name => 'Joel');
+is $obj5->name,    'Joel',         'base attribute';
+is $obj5->whisper, 'psst, joel',   'method from first role';
+is $obj5->hello,   'HEY! JOEL!!!', 'method from second role';
+
+# Multiple roles (mixed)
+my $obj6 = Mojo::RoleTest->with_roles('Mojo::RoleTest::Role::quiet', '+LOUD')
+  ->new(name => 'Joel');
+is $obj6->name,    'Joel',         'base attribute';
+is $obj6->whisper, 'psst, joel',   'method from first role';
+is $obj6->hello,   'HEY! JOEL!!!', 'method from second role';
+
+# Classes that are not subclasses of Mojo::Base
+my $stream = Mojo::ByteStream->with_roles('Mojo::RoleTest::Hello')->new;
+is $stream->hello, 'hello mojo!', 'right result';
+my $c = Mojo::Collection->with_roles('Mojo::RoleTest::Hello')->new;
+is $c->hello, 'hello mojo!', 'right result';
+my $dom = Mojo::DOM->with_roles('Mojo::RoleTest::Hello')->new;
+is $dom->hello, 'hello mojo!', 'right result';
+my $file = Mojo::File->with_roles('Mojo::RoleTest::Hello')->new;
+is $file->hello, 'hello mojo!', 'right result';
+
+done_testing();
+


Reply via email to