[Jifty-commit] r4750 - in jifty/branches/cssquery-refactor: . lib/Jifty lib/Jifty/Action lib/Jifty/Plugin lib/Jifty/Plugin/Authentication/CAS/Action lib/Jifty/Plugin/Gladiator lib/Jifty/Plugin/REST lib/Jifty/Web lib/Jifty/Web/Form share/web/templates/__jifty/webservices t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action t/TestApp-JiftyJS/share/web/static/css t/TestApp-JiftyJS/t t/TestApp/lib/TestApp t/TestApp/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Thu Dec 20 04:16:09 EST 2007


Author: gugod
Date: Thu Dec 20 04:16:08 2007
New Revision: 4750

Added:
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/Dispatcher.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/View.pm
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/AddTwoNumbers.pm
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/Play.pm
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/share/web/static/css/
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/share/web/static/css/app.css
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-AddTwoNumbers.t
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-Play.t
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/3-continuation.t
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/4-tangent.t
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/5-action.t
Modified:
   jifty/branches/cssquery-refactor/   (props changed)
   jifty/branches/cssquery-refactor/Makefile.PL
   jifty/branches/cssquery-refactor/lib/Jifty/Action/Record.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Collection.pm
   jifty/branches/cssquery-refactor/lib/Jifty/DateTime.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Dispatcher.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Authentication/CAS/Action/CASLogin.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/LeakTracker.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Monitoring.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Record.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Result.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Util.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Web/Form.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Web/Form/Field.pm
   jifty/branches/cssquery-refactor/lib/Jifty/Web/Menu.pm
   jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/json
   jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/yaml
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/View.pm
   jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/1-jifty-update.t
   jifty/branches/cssquery-refactor/t/TestApp/lib/TestApp/Dispatcher.pm
   jifty/branches/cssquery-refactor/t/TestApp/t/02-dispatch.t

Log:
 r8497 at GOP (orig r4679):  yves | 2007-12-14 05:51:07 +0800
 add missing continuation in CAS login plugin
 
 r8503 at GOP (orig r4685):  gugod | 2007-12-14 15:15:10 +0800
 Replace "is $html, ..." with $self->wait_for_text_present_ok
 
 Isolate current tests in a bare block, so we can put more tests in this file easily.
 
 r8504 at GOP (orig r4686):  gugod | 2007-12-14 15:38:57 +0800
 For testing continuation, add a "AddTwoNumber" wizard like the one in
 Jifty::Manual::Continuations, only it's written with TD rather then
 mason template.
 
 To manually test it, goto /c/page1 first. Type some number and hit
 enter. You sholud then visit /c/page2. Type some other number and hit
 enter. You should return to /c/page1 with the result of AddTwoNumber
 action shown in the message box.
 
 r8505 at GOP (orig r4687):  gugod | 2007-12-14 15:42:49 +0800
 Adda another URL that shows the same form as /c/page1/ to test if the
 form_return really return to the tangent point.
 
 r8506 at GOP (orig r4688):  gugod | 2007-12-14 17:02:57 +0800
 Finish two sets of selenium tests for testing continuation.
 
 The goal is to see if form_return actually returned to where it
 begins.  The entry point can be either '/c/page1', or
 '/c/page_another_one'.
 
 r8507 at GOP (orig r4689):  gugod | 2007-12-14 17:49:15 +0800
 Add a simple tangent/return test file, this is to protect the
 behaviour that, clicking on a "return" link should return to previous
 tangent point, or default location if none.
 
 r8508 at GOP (orig r4690):  gugod | 2007-12-14 18:40:39 +0800
 Add a test to test the link that updates multiple regions at once,
 and also showing an alert().
 
 r8509 at GOP (orig r4691):  gugod | 2007-12-14 20:42:55 +0800
 Add a "Play" action with various argument schema, and a test to test
 javascript behaviour based on the schema.
 
 The first test is to test if ajax canonicalized setting works.
 
 r8510 at GOP (orig r4692):  gugod | 2007-12-14 21:56:15 +0800
 Add canonicalization tests.
 
 r8514 at GOP (orig r4696):  jesse | 2007-12-15 15:12:14 +0800
  r73170 at pinglin:  jesse | 2007-12-15 02:09:57 -0500
   * A first pass attempt at a Devel::Gladiator plugin for Jifty. Doesn't seem to work very well
 
 r8523 at GOP (orig r4705):  sartak | 2007-12-15 20:30:38 +0800
  r49097 at onn:  sartak | 2007-12-15 07:30:02 -0500
  Rewrite the Gladiator plugin so that it now works, and do the log/view thing (which really wants to be generalized.. later)
 
 r8526 at GOP (orig r4708):  jesse | 2007-12-17 04:50:56 +0800
 
 * Revert mistaken commit. 
 * Fix menus to properly weaken "parent" relationships (and normalize _parent and parent)
 
 r8527 at GOP (orig r4709):  sartak | 2007-12-17 05:16:11 +0800
  r49124 at onn:  sartak | 2007-12-16 16:14:49 -0500
  LeakTracker: complain if Devel::Events::Generator::ObjectTracker isn't loaded in time (nothingmuch++)
 
 r8528 at GOP (orig r4710):  sartak | 2007-12-17 05:22:08 +0800
  r49130 at onn:  sartak | 2007-12-16 16:21:49 -0500
  Copying a reference unweakens it, so a small fix for that in JWFF->_action. But that isn't our leak, I think
 
 r8529 at GOP (orig r4711):  sartak | 2007-12-17 05:27:20 +0800
  r49133 at onn:  sartak | 2007-12-16 16:27:08 -0500
  Fix a real memory leak in Jifty::Web::Menu due to copying a weak reference. Woo!
 
 r8530 at GOP (orig r4712):  sartak | 2007-12-17 05:30:49 +0800
  r49135 at onn:  sartak | 2007-12-16 16:30:44 -0500
  Another copied weakref in Jifty::Web::Form::Field, though this code was just changed so I don't think it explains our white whale
 
 r8531 at GOP (orig r4713):  sartak | 2007-12-17 05:54:03 +0800
  r49137 at onn:  sartak | 2007-12-16 16:53:55 -0500
  Add Devel::Gladiator to Makefile.PL, other little fixes in here
 
 r8532 at GOP (orig r4714):  jesse | 2007-12-17 07:54:13 +0800
  r73218 at pinglin:  jesse | 2007-12-16 18:52:40 -0500
  * small fixes to make the tests run from the main harness
 
 r8540 at GOP (orig r4722):  sartak | 2007-12-17 19:57:35 +0800
  r49139 at onn:  sartak | 2007-12-17 06:55:58 -0500
  Revert 4650 (cssquery change) because ".error is no longer hidden for the region being replaced with ajax" in some browsers
 
 r8541 at GOP (orig r4723):  jesse | 2007-12-17 20:30:42 +0800
  r73700 at pinglin:  jesse | 2007-12-17 07:28:21 -0500
  * Attempt to weaken another reference to the current action that may be leaking
 
 r8542 at GOP (orig r4724):  clkao | 2007-12-18 02:06:06 +0800
 In deferred sub called from arguments, we need to use weakself.
 r8543 at GOP (orig r4725):  clkao | 2007-12-18 02:09:35 +0800
 oops, revert accidental changes in the deferred sub.
 r8544 at GOP (orig r4726):  sartak | 2007-12-18 03:53:38 +0800
 
 r8545 at GOP (orig r4727):  sartak | 2007-12-18 03:54:01 +0800
  r49156 at onn:  sartak | 2007-12-17 14:49:51 -0500
  More Makefile.PL tweaks
 
 r8546 at GOP (orig r4728):  sartak | 2007-12-18 03:54:04 +0800
  r49157 at onn:  sartak | 2007-12-17 14:53:28 -0500
  Typo fix in Makefile.PL
 
 r8548 at GOP (orig r4732):  falcone | 2007-12-18 12:07:26 +0800
  r27631 at ketch:  falcone | 2007-12-17 23:05:12 -0500
  * add a check for the op to the dispatcher condition cache
    because on and the other ops generate different regexps
 
 r8549 at GOP (orig r4733):  alexmv | 2007-12-18 12:46:21 +0800
  r25896 at zoq-fot-pik:  chmrr | 2007-12-17 23:44:06 -0500
   * Lockfile support
 
 r8552 at GOP (orig r4736):  sartak | 2007-12-19 01:45:42 +0800
  r49191 at onn:  sartak | 2007-12-18 12:45:27 -0500
  Revert 4649 js memoization which caused .error div problems
 
 r8553 at GOP (orig r4737):  alexmv | 2007-12-19 05:17:14 +0800
  r25921 at zoq-fot-pik:  chmrr | 2007-12-18 16:16:05 -0500
   * Bump Scalar::Defer dependency, for great lack-of-memory-leak justice
 
 r8554 at GOP (orig r4738):  sartak | 2007-12-19 08:30:22 +0800
  r49193 at onn:  sartak | 2007-12-18 19:27:52 -0500
  Move the REST object walking into Jifty::Result so that it may be reused
 
 r8555 at GOP (orig r4739):  sartak | 2007-12-19 09:12:10 +0800
  r49197 at onn:  sartak | 2007-12-18 20:11:39 -0500
  Make the json and yaml webservices use Result->from_hash
 
 r8556 at GOP (orig r4740):  sartak | 2007-12-19 09:23:08 +0800
  r49199 at onn:  sartak | 2007-12-18 20:22:56 -0500
  Missing $server in a test? I doubt this is intentional, so fixing
 
 r8557 at GOP (orig r4741):  sartak | 2007-12-19 10:22:13 +0800
  r49203 at onn:  sartak | 2007-12-18 21:22:02 -0500
  Give the interesting classes jifty_serialize_format instead of hardcoding in recurse_object_to_data (obra++)
 
 r8558 at GOP (orig r4742):  sartak | 2007-12-19 12:23:56 +0800
  r49205 at onn:  sartak | 2007-12-18 23:23:44 -0500
  Two small fixes for Jifty::Result changes: missed two fields and for backcompat we need to bless the resulting hash into Jifty::Result
 
 r8559 at GOP (orig r4743):  sartak | 2007-12-19 12:39:22 +0800
  r49209 at onn:  sartak | 2007-12-18 23:39:11 -0500
  Actually, no, don't bless the result of Jifty::Result->as_hash
 
 r8562 at GOP (orig r4746):  sartak | 2007-12-20 00:59:13 +0800
  r49215 at onn:  sartak | 2007-12-19 11:58:58 -0500
  Eugh, don't eval send_action results in mech
 
 r8563 at GOP (orig r4747):  sartak | 2007-12-20 01:20:27 +0800
  r49217 at onn:  sartak | 2007-12-19 12:20:11 -0500
  Revert 4746 because it's actually not evil at all
 
 r8564 at GOP (orig r4748):  sartak | 2007-12-20 05:57:26 +0800
  r49311 at onn:  sartak | 2007-12-19 16:57:08 -0500
  Use record->jifty_serialize_format instead of the old result->_record_to_data
 


Modified: jifty/branches/cssquery-refactor/Makefile.PL
==============================================================================
--- jifty/branches/cssquery-refactor/Makefile.PL	(original)
+++ jifty/branches/cssquery-refactor/Makefile.PL	Thu Dec 20 04:16:08 2007
@@ -64,7 +64,7 @@
 requires('Object::Declare' => '0.13');
 requires('PadWalker');
 requires('Params::Validate');
-requires('Scalar::Defer' => '0.10');
+requires('Scalar::Defer' => '0.12');
 requires('Shell::Command');
 requires('String::Koremutake');
 requires('SQL::ReservedWords');
@@ -160,21 +160,16 @@
         recommends('XML::Simple'),
         recommends('Image::Info'), # for testing
     ],
-    'Memory Leak Plugin' => [
+    'Memory Leak Plugins' => [
         -default => 0,
-        recommends('Devel::Events' => '0.02'),
-        recommends('Devel::Events::Handler::ObjectTracker'),
-        recommends('Devel::Events::Generator::Objects'),
+        recommends('Devel::Events::Objects' => '0.02'), # Devel::Events::Handler::ObjectTracker Devel::Events::Generator::Objects
         recommends('Devel::Size'),
+        recommends('Devel::Gladiator'),
         recommends('Proc::ProcessTable'),
     ],
     'OAuth Plugin' => [
         -default => 0,
-        recommends('Net::OAuth::Request' => '0.04'),
-        recommends('Net::OAuth::RequestTokenRequest'),
-        recommends('Net::OAuth::AccessTokenRequest'),
-        recommends('Net::OAuth::ProtectedResourceRequest'),
-
+        recommends('Net::OAuth::Request' => '0.04'), # Net::OAuth::RequestTokenRequest Net::OAuth::AccessTokenRequest Net::OAuth::ProtectedResourceRequest
         recommends('Crypt::OpenSSL::RSA'),
         recommends('Digest::HMAC_SHA1'),
     ],

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Action/Record.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Action/Record.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Action/Record.pm	Thu Dec 20 04:16:08 2007
@@ -156,8 +156,10 @@
 
     for my $field ( keys %$arguments ) {
         if ( my $function = $self->record->can($field) ) {
+            my $weakself = $self;
+            Scalar::Util::weaken $weakself;
             $arguments->{$field}->{default_value} = defer {
-                my $val = $function->( $self->record );
+                my $val = $function->( $weakself->record );
                 # If the current value is actually a pointer to
                 # another object, turn it into an ID
                 return $val->id if (blessed($val) and $val->isa('Jifty::Record'));

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Collection.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Collection.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Collection.pm	Thu Dec 20 04:16:08 2007
@@ -144,6 +144,19 @@
     return ( current_user => $self->current_user );
 }
 
+=head2 jifty_serialize_format
+
+This returns an array reference of the individual records that make up this
+collection.
+
+=cut
+
+sub jifty_serialize_format {
+    my $records = shift->items_array_ref;
+
+    return [ map { $_->jifty_serialize_format(@_) } @$records ];
+}
+
 =head1 SEE ALSO
 
 L<Jifty::DBI::Collection>, L<Jifty::Object>, L<Jifty::Record>

Modified: jifty/branches/cssquery-refactor/lib/Jifty/DateTime.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/DateTime.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/DateTime.pm	Thu Dec 20 04:16:08 2007
@@ -268,6 +268,24 @@
     return 1;
 }
 
+=head2 jifty_serialize_format
+
+This returns a DateTime (or string) consistent with Jifty's date format.
+
+=cut
+
+sub jifty_serialize_format {
+    my $dt = shift;
+
+    # if it looks like just a date, then return just the date portion
+    return $dt->ymd
+        if lc($dt->time_zone->name) eq 'floating'
+        && $dt->hms('') eq '000000';
+
+    # otherwise let stringification take care of it
+    return $dt;
+}
+
 =head1 WHY?
 
 There are other ways to do some of these things and some of the decisions here may seem arbitrary, particularly if you read the code. They are.

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Dispatcher.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Dispatcher.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Dispatcher.pm	Thu Dec 20 04:16:08 2007
@@ -985,7 +985,9 @@
     # Previously compiled (eg. a qr{} -- return it verbatim)
     return $cond if ref $cond;
 
-    unless ( $CONDITION_CACHE{$cond} ) {
+    my $cachekey = join('-', (($Dispatcher->{rule} eq 'on') ? 'on' : 'in'),
+                             $cond);
+    unless ( $CONDITION_CACHE{$cachekey} ) {
 
         my $compiled = $cond;
 
@@ -1027,9 +1029,9 @@
         if ( !$has_capture ) {
             $compiled = "($compiled)";
         }
-        $CONDITION_CACHE{$cond} = qr{$compiled};
+        $CONDITION_CACHE{$cachekey} = qr{$compiled};
     }
-    return $CONDITION_CACHE{$cond};
+    return $CONDITION_CACHE{$cachekey};
 }
 
 =head2 _compile_glob METAEXPRESSION

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Authentication/CAS/Action/CASLogin.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Authentication/CAS/Action/CASLogin.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Authentication/CAS/Action/CASLogin.pm	Thu Dec 20 04:16:08 2007
@@ -70,6 +70,9 @@
 #    	$ENV{HTTP_HOST}.'/caslogin';
     
     my $service_url = Jifty->web->url.'/caslogin';
+    if ( Jifty->web->request->continuation ) {
+        $service_url .= '?J:C='.Jifty->web->request->continuation_id;
+    };
 
     if (! $ticket) {
         my $login_url = $plugin->CAS->login_url( $service_url );

Added: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator.pm
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator.pm	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,127 @@
+package Jifty::Plugin::Gladiator;
+use strict;
+use warnings;
+use base qw/Jifty::Plugin Class::Data::Inheritable/;
+__PACKAGE__->mk_accessors(qw/prev_data/);
+
+use Devel::Gladiator;
+use List::Util 'reduce';
+
+our @requests;
+
+our $VERSION = 0.01;
+
+=head2 init
+
+init installs the trigger needed before each HTTP request. It also establishes
+the baseline for all times and creates the log path.
+
+=cut
+
+sub init {
+    my $self = shift;
+    my %args = (
+        @_,
+    );
+
+    return if $self->_pre_init;
+
+    Jifty::Handler->add_trigger(
+        after_request => sub { $self->after_request(@_) }
+    );
+}
+
+=head2 after_request
+
+=cut
+
+sub after_request {
+    my $self    = shift;
+    my $handler = shift;
+    my $cgi     = shift;
+
+    # walk the arena, noting the type of each value
+    my %types;
+    for (@{ Devel::Gladiator::walk_arena() }) {
+        ++$types{ ref $_ };
+    }
+
+    # basic stats
+    my $all_values = reduce { $a + $b } values %types;
+    my $all_types  = keys %types;
+    my $new_values = 0;
+    my $new_types  = 0;
+
+    my %prev = %{ $self->prev_data || {} };
+
+    # copy so when we modify %types it doesn't affect prev_data
+    my %new_prev = %types;
+    $self->prev_data(\%new_prev);
+
+    # find the difference
+    for my $type (keys %types) {
+        my $diff = $types{$type} - ($prev{$type} || 0);
+
+        if ($diff != 0) {
+            $new_values += $diff;
+            ++$new_types;
+        }
+
+        $types{$type} = {
+            all => $types{$type},
+            new => $diff,
+        }
+    }
+
+    push @requests, {
+        id         => 1 + @requests,
+        url        => $cgi->url(-absolute=>1,-path_info=>1),
+        time       => scalar gmtime,
+
+        all_values => $all_values,
+        all_types  => $all_types,
+        new_values => $new_values,
+        new_types  => $new_types,
+        diff       => \%types,
+    };
+}
+
+
+=head1 NAME
+
+Jifty::Plugin::Gladiator - find leaks
+
+=head1 DESCRIPTION
+
+This plugin will attempt to output diffs between the current contents of memory after each request.
+
+
+=head1 USAGE
+
+Add the following to your site_config.yml
+
+ framework:
+   Plugins:
+     - Gladiator: {}
+
+=head2 OPTIONS
+
+=over 4
+
+
+=back
+
+=head1 SEE ALSO
+
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+
+

Added: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/Dispatcher.pm	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,49 @@
+package Jifty::Plugin::Gladiator::Dispatcher;
+use warnings;
+use strict;
+
+use Jifty::Dispatcher -base;
+
+# http://your.app/arena
+on '/__jifty/admin/arena' => run {
+    set 'skip_zero' => 1;
+    show "/__jifty/admin/arena/all";
+};
+
+# http://your.app/arena/all
+on '/__jifty/admin/arena/all' => run {
+    set 'skip_zero' => 0;
+    show "/__jifty/admin/arena/all";
+};
+
+# http://your.app/arena/clear
+on '/__jifty/admin/arena/clear' => run {
+    @Jifty::Plugin::Gladiator::requests = ();
+    set 'skip_zero' => 1;
+    redirect "/__jifty/admin/arena";
+};
+
+# http://your.app/arena/xxx
+on '/__jifty/admin/arena/#' => run {
+    abort(404) if $1 < 1;
+    my $arena = $Jifty::Plugin::Gladiator::requests[$1 - 1]
+        or abort(404);
+    set arena => $arena;
+    show "/__jifty/admin/arena/one";
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Gladiator>, L<Jifty::Plugin::Gladiator::View>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+
+

Added: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Gladiator/View.pm	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,114 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Gladiator::View;
+use Jifty::View::Declare -base;
+use Scalar::Util 'blessed';
+
+=head1 NAME
+
+Jifty::Plugin::Gladiator::View - Views for database arena
+
+=head1 TEMPLATES
+
+=cut
+
+template '/__jifty/admin/arena/all' => page {
+    my $skip_zero = get 'skip_zero';
+
+    h1 { "Queries" }
+    p {
+        if ($skip_zero) {
+            a { attr { href => "/__jifty/admin/arena/all" }
+                "Show zero-arena requests" }
+        }
+        else {
+            a { attr { href => "/__jifty/admin/arena" }
+                "Hide zero-arena requests" }
+        }
+        a { attr { href => "/__jifty/admin/arena/clear" }
+            "Clear arena log" }
+    }
+    hr {}
+
+    h3 { "All arena" };
+    table {
+        row {
+            th { "ID"         }
+            th { "New values" }
+            th { "New types"  }
+            th { "All values" }
+            th { "All types"  }
+            th { "URL"        }
+        };
+
+        for (@Jifty::Plugin::Gladiator::requests)
+        {
+            next if $skip_zero && $_->{new_values} == 0;
+
+            row {
+                cell { a {
+                    attr { href => "/__jifty/admin/arena/$_->{id}" }
+                    $_->{id} } }
+
+                cell { $_->{new_values} }
+                cell { $_->{new_types}  }
+                cell { $_->{all_values} }
+                cell { $_->{all_types}  }
+                cell { $_->{url}        }
+            };
+        }
+    }
+};
+
+template '/__jifty/admin/arena/one' => page {
+    my $arena = get 'arena';
+
+    h1 { "Queries from Request $arena->{id}" }
+    ul {
+        li { "URL: $arena->{url}" }
+        li { "At: " . $arena->{time} }
+        li { "New values: $arena->{new_values}" }
+        li { "New types:  $arena->{new_types}"  }
+        li { "All values: $arena->{all_values}" }
+        li { "All types:  $arena->{all_types}"  }
+    }
+
+    table {
+        row {
+            th { "Type" }
+            th { "New" }
+            th { "All" }
+        };
+
+        my @sorted = sort {
+            $arena->{diff}->{$b}->{new} <=> $arena->{diff}->{$a}->{new}
+                                         ||
+            $arena->{diff}->{$b}->{all} <=> $arena->{diff}->{$a}->{all}
+        } keys %{ $arena->{diff} };
+
+        for my $type (@sorted) {
+            row {
+                cell { $type }
+                cell { $arena->{diff}->{$type}->{new} }
+                cell { $arena->{diff}->{$type}->{all} }
+            }
+        }
+    }
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Gladiator>, L<Jifty::Plugin::Gladiator::Dispatcher>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+
+

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/LeakTracker.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Plugin/LeakTracker.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/LeakTracker.pm	Thu Dec 20 04:16:08 2007
@@ -4,6 +4,13 @@
 package Jifty::Plugin::LeakTracker;
 use base qw/Jifty::Plugin Class::Data::Inheritable/;
 use Data::Dumper;
+
+BEGIN {
+    if (!$INC{"Devel/Events/Generator/Objects.pm"}) {
+        Jifty->log->error("Devel::Events::Generator::Objects must be compiled very early so that it can override 'bless' in time. Usually this means you must run your Jifty application with: perl -MDevel::Events::Generator::Objects bin/jifty");
+    }
+}
+
 use Devel::Events::Handler::ObjectTracker;
 use Devel::Events::Generator::Objects;
 use Devel::Size 'total_size';

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Monitoring.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Monitoring.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/Monitoring.pm	Thu Dec 20 04:16:08 2007
@@ -52,7 +52,7 @@
 
 =cut
 
-__PACKAGE__->mk_accessors(qw/base_classes monitors now current_monitor/);
+__PACKAGE__->mk_accessors(qw/base_classes monitors now current_monitor lockfile has_lock/);
 
 our @EXPORT = qw/monitor every
                  minute minutes
@@ -194,6 +194,7 @@
     my @path = $args{path} ? @{$args{path}} : (Jifty->app_class("Monitor"));
     $self->base_classes(\@path);
     $self->monitors({});
+    $self->lockfile($args{lockfile} || "var/monitoring.pid");
     local $Jifty::Plugin::Monitoring::self = $self;
     Jifty::Module::Pluggable->import(
         require => 1,
@@ -273,6 +274,7 @@
 
 sub run_monitors {
     my $self = shift;
+    return unless $self->lock;
     my $now = Jifty::DateTime->now->truncate( to => "minute" );
     $now->set_time_zone("UTC");
     $self->now($now);
@@ -298,4 +300,19 @@
     $self->current_monitor(undef);
 }
 
+sub lock {
+    my $self = shift;
+    return if -e $self->lockfile;
+    open PID, ">", $self->lockfile;
+    print PID $$;
+    close PID;
+    $self->has_lock(1);
+    return 1;
+}
+
+sub DESTROY {
+    my $self = shift;
+    unlink $self->lockfile if $self->has_lock;
+}
+
 1;

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Plugin/REST/Dispatcher.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Plugin/REST/Dispatcher.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Plugin/REST/Dispatcher.pm	Thu Dec 20 04:16:08 2007
@@ -87,142 +87,6 @@
 }
 
 
-=head2 stringify LIST
-
-Takes a list of values and forces them into strings.  Right now all it does
-is concatenate them to an empty string, but future versions might be more
-magical.
-
-=cut
-
-sub stringify {
-    # XXX: allow configuration to specify model fields that are to be
-    # expanded
-    my @r;
-
-    for (@_) {
-        if (UNIVERSAL::isa($_, 'Jifty::Record')) {
-            push @r, reference_to_data($_);
-        }
-        elsif (UNIVERSAL::isa($_, 'Jifty::DateTime')) {
-            push @r, _datetime_to_data($_);
-        }
-        elsif (defined $_) {
-            push @r, '' . $_; # force stringification
-        }
-        else {
-            push @r, undef;
-        }
-    }
-
-    return wantarray ? @r : $r[-1];
-}
-
-=head2 reference_to_data
-
-provides a saner output format for models than MyApp::Model::Foo=HASH(0x1800568)
-
-=cut
-
-sub reference_to_data {
-    my $obj = shift;
-    my ($model) = map { s/::/./g; $_ } ref($obj);
-    return { jifty_model_reference => 1, id => $obj->id, model => $model };
-}
-
-=head2 object_to_data OBJ
-
-Takes an object and converts the known types into simple data structures.
-
-Current known types:
-
-  Jifty::DBI::Collection
-  Jifty::DBI::Record
-  Jifty::DateTime
-
-=cut
-
-sub object_to_data {
-    my $obj = shift;
-    
-    my %types = (
-        'Jifty::DBI::Collection' => \&_collection_to_data,
-        'Jifty::DBI::Record'     => \&_record_to_data,
-        'Jifty::DateTime'        => \&_datetime_to_data,
-    );
-
-    for my $type ( keys %types ) {
-        if ( UNIVERSAL::isa( $obj, $type ) ) {
-            return $types{$type}->( $obj );
-        }
-    }
-
-    # As the last resort, return the object itself and expect the $accept-specific
-    # renderer to format the object as e.g. YAML or JSON data.
-    return $obj;
-}
-
-sub _collection_to_data {
-    my $records = shift->items_array_ref;
-    return [ map { _record_to_data( $_ ) } @$records ];
-}
-
-sub _record_to_data {
-    my $record = shift;
-    # We could use ->as_hash but this method avoids transforming refers_to
-    # columns into JDBI objects
-
-    # XXX: maybe just test ->virtual?
-    my %data   = map {
-                    $_ => (UNIVERSAL::isa( $record->column( $_ )->refers_to,
-                                           'Jifty::DBI::Collection' ) ||
-                           $record->column($_)->container
-                             ? undef
-                             : stringify( $record->_value( $_ ) ) )
-                 } $record->readable_attributes;
-    return \%data;
-}
-
-sub _datetime_to_data {
-    my $dt = shift;
-
-    # if it looks like just a date, then return just the date portion
-    return $dt->ymd
-        if lc($dt->time_zone->name) eq 'floating'
-        && $dt->hms('') eq '000000';
-
-    # otherwise let stringification take care of it
-    return $dt;
-}
-
-=head2 recurse_object_to_data REF
-
-Takes a reference, and calls C<object_to_data> on it if that is
-meaningful.  If it is an arrayref, or recurses on each element.  If it
-is a hashref, recurses on each value.  Returns the new datastructure.
-
-=cut
-
-sub recurse_object_to_data {
-    my $o = shift;
-    return $o unless ref $o;
-
-    my $updated = object_to_data($o);
-    if ($o ne $updated) {
-        return $updated;
-    } elsif (ref $o eq "ARRAY") {
-        my @a = map {recurse_object_to_data($_)} @{$o};
-        return \@a;
-    } elsif (ref $o eq "HASH") {
-        my %h;
-        $h{$_} = recurse_object_to_data($o->{$_}) for keys %{$o};
-        return \%h;
-    } else {
-        return $o;
-    }
-}
-
-
 =head2 list PREFIX items
 
 Takes a URL prefix and a set of items to render. passes them on.
@@ -528,7 +392,8 @@
     $col->order_by( column => $column );
 
     list( [ 'model', $model, $column ],
-        map { stringify($_->$column()) } @{ $col->items_array_ref || [] } );
+        map { Jifty::Util->stringify($_->$column()) }
+            @{ $col->items_array_ref || [] } );
 }
 
 
@@ -549,7 +414,8 @@
     # Check that the field is actually a column (and not some other method)
     abort(404) if not scalar grep { $_->name eq $field } $rec->columns;
 
-    outs( [ 'model', $model, $column, $key, $field ], stringify($rec->$field()) );
+    outs( [ 'model', $model, $column, $key, $field ],
+          Jifty::Util->stringify($rec->$field()) );
 }
 
 =head2 show_item $model, $column, $key
@@ -565,7 +431,9 @@
     my $rec = $model->new;
     $rec->load_by_cols( $column => $key );
     $rec->id or abort(404);
-    outs( ['model', $model, $column, $key],  { map {$_ => stringify($rec->$_())} map {$_->name} $rec->columns});
+    outs( ['model', $model, $column, $key], 
+        { map { $_ => Jifty::Util->stringify($rec->$_()) }
+              map {$_->name} $rec->columns});
 }
 
 =head2 create_item
@@ -769,24 +637,8 @@
         } 'model', ref($rec), 'id', $rec->id);
         Jifty->handler->apache->header_out('Location' => $url);
     }
-    
-    my $result = $action->result;
 
-    my $out = {};
-    $out->{success} = $result->success;
-    $out->{message} = $result->message;
-    $out->{error} = $result->error;
-    $out->{field_errors} = {$result->field_errors};
-    for (keys %{$out->{field_errors}}) {
-        delete $out->{field_errors}->{$_} unless $out->{field_errors}->{$_};
-    }
-    $out->{field_warnings} = {$result->field_warnings};
-    for (keys %{$out->{field_warnings}}) {
-        delete $out->{field_warnings}->{$_} unless $out->{field_warnings}->{$_};
-    }
-    $out->{content} = recurse_object_to_data($result->content);
-    
-    outs(undef, $out);
+    outs(undef, $action->result->as_hash);
 
     last_rule;
 }

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Record.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Record.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Record.pm	Thu Dec 20 04:16:08 2007
@@ -827,4 +827,28 @@
     }
 }
 
+=head2 jifty_serialize_format
+
+This is used to create a hash reference of the object's values. Unlike
+Jifty::DBI::Record->as_hash, this won't transform refers_to columns into JDBI
+objects
+
+=cut
+
+sub jifty_serialize_format {
+    my $record = shift;
+    my %data;
+
+    # XXX: maybe just test ->virtual?
+    for ($record->readable_attributes) {
+        next if UNIVERSAL::isa($record->column($_)->refers_to,
+                               'Jifty::DBI::Collection');
+        next if $record->column($_)->container;
+
+        $data{$_} = Jifty::Util->stringify($record->_value($_));
+    }
+
+    return \%data;
+}
+
 1;

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Result.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Result.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Result.pm	Thu Dec 20 04:16:08 2007
@@ -179,4 +179,69 @@
     return $self->_content->{$key};
 }
 
+=head2 as_hash
+
+This returns the results as a hash to be given directly to the end user
+(usually via REST or webservices). The difference between
+C<< $result->as_hash >> and C<%$result> is that the latter will expand
+everything as deeply as possible. The former won't inflate C<refers_to>
+columns, among other things.
+
+=cut
+
+sub as_hash {
+    my $self = shift;
+
+    my $out = {
+        success        => $self->success,
+        failure        => $self->failure,
+        action_class   => $self->action_class,
+        message        => $self->message,
+        error          => $self->error,
+        field_errors   => { $self->field_errors },
+        field_warnings => { $self->field_warnings },
+        content        => $self->_recurse_object_to_data($self->content),
+    };
+
+    for (keys %{$out->{field_errors}}) {
+        delete $out->{field_errors}->{$_} unless $out->{field_errors}->{$_};
+    }
+    for (keys %{$out->{field_warnings}}) {
+        delete $out->{field_warnings}->{$_} unless $out->{field_warnings}->{$_};
+    }
+
+    return $out;
+}
+
+sub _recurse_object_to_data {
+    my $self = shift;
+    my $o = shift;
+
+    return $o if !ref($o);
+
+    if (ref($o) eq 'ARRAY') {
+        return [ map { $self->_recurse_object_to_data($_) } @$o ];
+    }
+    elsif (ref($o) eq 'HASH') {
+        my %h;
+        $h{$_} = $self->_recurse_object_to_data($o->{$_}) for keys %$o;
+        return \%h;
+    }
+
+    return $self->_object_to_data($o);
+}
+
+sub _object_to_data {
+    my $self = shift;
+    my $o = shift;
+
+    if ($o->can('jifty_serialize_format')) {
+        return $o->jifty_serialize_format($self);
+    }
+
+    # As the last resort, return the object itself and expect the
+    # $accept-specific renderer to format the object as e.g. YAML or JSON data.
+    return $o;
+}
+
 1;

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Util.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Util.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Util.pm	Thu Dec 20 04:16:08 2007
@@ -334,6 +334,47 @@
     })->create_str;
 }
 
+=head2 reference_to_data Object
+
+Provides a saner output format for models than
+C<MyApp::Model::Foo=HASH(0x1800568)>.
+
+=cut
+
+sub reference_to_data {
+    my ($self, $obj) = @_;
+    (my $model = ref($obj)) =~ s/::/./g;
+    return { jifty_model_reference => 1, id => $obj->id, model => $model };
+}
+
+=head2 stringify LIST
+
+Takes a list of values and forces them into strings.  Right now all it does
+is concatenate them to an empty string, but future versions might be more
+magical.
+
+=cut
+
+sub stringify {
+    my $self = shift;
+
+    my @r;
+
+    for (@_) {
+        if (UNIVERSAL::isa($_, 'Jifty::Record')) {
+            push @r, Jifty::Util->reference_to_data($_);
+        }
+        elsif (defined $_) {
+            push @r, '' . $_; # force stringification
+        }
+        else {
+            push @r, undef;
+        }
+    }
+
+    return wantarray ? @r : $r[-1];
+}
+
 =head1 AUTHOR
 
 Various folks at Best Practical Solutions, LLC.

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Web/Form.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Web/Form.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Web/Form.pm	Thu Dec 20 04:16:08 2007
@@ -7,6 +7,8 @@
 
 __PACKAGE__->mk_accessors(qw(actions printed_actions name call is_open disable_autocomplete target submit_to onsubmit));
 
+use Scalar::Util qw/weaken/;
+
 =head1 NAME
 
 Jifty::Web::Form - Tools for rendering and dealing with HTML forms
@@ -149,6 +151,7 @@
     my $self = shift;
     my $action = shift;
     $self->actions->{ $action->moniker } =  $action;
+    weaken $self->actions->{ $action->moniker};
     return $action;
 }
 

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Web/Form/Field.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Web/Form/Field.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Web/Form/Field.pm	Thu Dec 20 04:16:08 2007
@@ -44,7 +44,7 @@
 
 use base 'Jifty::Web::Form::Element';
 
-use Scalar::Util;
+use Scalar::Util qw/weaken/;
 use Scalar::Defer qw/force/;
 use HTML::Entities;
 
@@ -297,13 +297,17 @@
 =cut
 
 sub action {
-    my $self   = shift;
-    my $action = $self->_action(@_);
+    my $self = shift;
+
+    if (@_) {
+        $self->_action(@_);
+
+        # weaken our circular reference
+        weaken $self->{_action};
+    }
+
+    return $self->_action;
 
-    # If we're setting the action, we need to weaken
-    # the reference to not get caught in a loop
-    Scalar::Util::weaken( $self->{_action} ) if @_;
-    return $action;
 }
 
 =head2 current_value

Modified: jifty/branches/cssquery-refactor/lib/Jifty/Web/Menu.pm
==============================================================================
--- jifty/branches/cssquery-refactor/lib/Jifty/Web/Menu.pm	(original)
+++ jifty/branches/cssquery-refactor/lib/Jifty/Web/Menu.pm	Thu Dec 20 04:16:08 2007
@@ -2,9 +2,9 @@
 
 use base qw/Class::Accessor::Fast/;
 use URI;
-use Scalar::Util ();
+use Scalar::Util qw(weaken);
 
-__PACKAGE__->mk_accessors(qw(label parent sort_order link target escape_label class));
+__PACKAGE__->mk_accessors(qw(label _parent sort_order link target escape_label class));
 
 =head1 NAME
 
@@ -23,9 +23,17 @@
 
 sub new {
     my $package = shift;
+    my $args = ref($_[0]) eq 'HASH' ? shift @_ : {@_};
+
+    my $parent = delete $args->{'parent'};
+
     # Class::Accessor only wants a hashref;
-    $package->SUPER::new( ref($_[0]) eq 'HASH' ? @_ : {@_} );
+    my $self = $package->SUPER::new( $args);
 
+    # make sure our reference is weak
+    $self->parent($parent) if defined $parent;
+
+    return $self;
 }
 
 
@@ -35,16 +43,24 @@
 
 =cut
 
-sub label {
-    my $self = shift;
-    $self->{label} = shift if @_;
-    return $self->{label};
-}
-
 =head2 parent [MENU]
 
 Gets or sets the parent L<Jifty::Web::Menu> of this item; this defaults
-to null.
+to null. This ensures that the reference is weakened.
+
+=cut
+
+
+sub parent {
+    my $self = shift;
+    if (@_) {
+        $self->_parent(@_);
+        weaken $self->{_parent};
+    }
+
+    return $self->_parent;
+}
+
 
 =head2 sort_order [NUMBER]
 

Modified: jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/json
==============================================================================
--- jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/json	(original)
+++ jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/json	Thu Dec 20 04:16:08 2007
@@ -1,2 +1,13 @@
 % $r->content_type("text/x-json");
-<% Jifty::JSON::objToJson({Jifty->web->response->results}) |n%>
+<% Jifty::JSON::objToJson(\%results) |n%>
+
+<%INIT>
+my %results = Jifty->web->response->results;
+for (values %results) {
+    $_ = $_->as_hash;
+
+    # backwards compatibility :(
+    $_->{_content} = delete $_->{content};
+}
+</%INIT>
+

Modified: jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/yaml
==============================================================================
--- jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/yaml	(original)
+++ jifty/branches/cssquery-refactor/share/web/templates/__jifty/webservices/yaml	Thu Dec 20 04:16:08 2007
@@ -1,2 +1,13 @@
 % $r->content_type("text/x-yaml");
-<% Jifty::YAML::Dump({Jifty->web->response->results}) |n%>
+<% Jifty::YAML::Dump(\%results) |n%>
+
+<%INIT>
+my %results = Jifty->web->response->results;
+for (values %results) {
+    $_ = $_->as_hash;
+
+    # backwards compatibility :(
+    $_->{_content} = delete $_->{content};
+}
+</%INIT>
+

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/AddTwoNumbers.pm
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/AddTwoNumbers.pm	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+
+=head1 NAME
+
+TestApp::JiftyJS::Action::AddTwoNumbers
+
+=cut
+
+package TestApp::JiftyJS::Action::AddTwoNumbers;
+use base qw/TestApp::JiftyJS::Action Jifty::Action/;
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+    param first_number  => type is 'text';
+    param second_number => type is 'text';
+};
+
+=head2 take_action
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    my $one = $self->argument_value("first_number");
+    my $two = $self->argument_value("second_number");
+    $self->result->message("Got " . ($one + $two));
+    return 1;
+}
+
+1;

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/Play.pm
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/Action/Play.pm	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,58 @@
+use strict;
+use warnings;
+
+=head1 NAME
+
+TestApp::JiftyJS::Action::Play
+
+=cut
+
+package TestApp::JiftyJS::Action::Play;
+use base qw/TestApp::JiftyJS::Action Jifty::Action/;
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+    param vanilla => type is 'text';
+
+    param mood =>
+        type is 'text',
+        ajax validates,
+        valid are qw(happy angry normal);
+
+    param tags =>
+        type is 'text',
+        ajax canonicalizes;
+};
+
+=head2 take_action
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    $self->report_success if not $self->result->failure;
+    return 1;
+}
+
+=head2 report_success
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    # Your success message here
+    $self->result->message('Success');
+}
+
+sub canonicalize_tags {
+    my ($self, $value) = @_;
+    my $v = lc($value);
+    $v =~ s/\s+/ /g;
+    $v =~ s/^\s*//g;
+    $v =~ s/\s*$//g;
+
+    return $v;
+}
+
+1;
+

Modified: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/View.pm
==============================================================================
--- jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/View.pm	(original)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/lib/TestApp/JiftyJS/View.pm	Thu Dec 20 04:16:08 2007
@@ -61,4 +61,88 @@
     p { "Region Two" }
 };
 
+template '/region/multiupdate' => page {
+    hyperlink(
+        id => 'update',
+        label => "Update All",
+        onclick => [
+            "alert(42);",
+            { region => 'content1', replace_with => 'region1' },
+            { region => 'content2', replace_with => 'region2' },
+            { region => 'content3', replace_with => 'hello_world', arguments => { name => "Pony" } },
+        ]
+    );
+
+    for (1..3) {
+        with(class=>'column'), div {
+            render_region( name => "content$_" );
+        }
+    }
+    with(style=>"clear:both;"), div {};
+};
+
+# Templtes for testing continuation. Using the example in Jifty::Manual::Continuations
+private template '/c/_first_number_form' => sub {
+    my $action = new_action(class => 'AddTwoNumbers');
+    form {
+        $action->form_field( 'first_number' )->render;
+        $action->form_field( 'second_number',
+                             default_value => {
+                                 request_argument => "number",
+                             }
+                         )->render;
+        tangent(
+            url => '/c/page2',
+            submit => $action,
+            label => "Enter a second number"
+        );
+    };
+};
+
+template '/c/page1' => page {
+    show('/c/_first_number_form');
+};
+
+template '/c/page_another_one' => page {
+    show('/c/_first_number_form');
+};
+
+template '/c/page2' => page {
+    form {
+        label { "Second Number" };
+        outs_raw('<input type="text" class="text" name="number" />');
+        form_return( label => "Pick", as_button => 1);
+    }
+};
+
+### tangent/reutrn test temapltes
+
+template '/tangent/returner' => page {
+    Jifty->web->return( label => "Go Back", to => "/", id => 'returner' )->render;
+};
+
+template '/tangent/page1' => page {
+    tangent( label => "Go to Returner", url => "/tangent/returner", id => 'to-returner' );
+};
+
+template '/tangent/page2' => page {
+    tangent( label => "Go to Returner", url => "/tangent/returner", id => 'to-returner' );
+};
+
+template '/tangent/page3' => page {
+    hyperlink( label => "Go to Returner", url => "/tangent/returner", id => 'to-returner' );
+};
+
+
+### action field test templates
+
+template '/act/play' => page {
+    my $a = new_action(class => 'Play');
+    form {
+        render_action($a);
+        form_submit( label => "Submit" );
+    };
+};
+
+
 1;

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/share/web/static/css/app.css
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/share/web/static/css/app.css	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,8 @@
+
+div.column {
+    width:200px;
+    padding-left:10px;
+    padding-right:10px;
+    float:left;
+}
+

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-AddTwoNumbers.t
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-AddTwoNumbers.t	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A (very) basic test harness for the AddTwoNumbers action.
+
+=cut
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 1;
+
+# Make sure we can load the action
+use_ok('TestApp::JiftyJS::Action::AddTwoNumbers');
+

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-Play.t
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/00-action-Play.t	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A (very) basic test harness for the Play action.
+
+=cut
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 1;
+
+# Make sure we can load the action
+use_ok('TestApp::JiftyJS::Action::Play');
+

Modified: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/1-jifty-update.t
==============================================================================
--- jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/1-jifty-update.t	(original)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/1-jifty-update.t	Thu Dec 20 04:16:08 2007
@@ -4,7 +4,7 @@
 use warnings;
 use lib 't/lib';
 use Jifty::SubTest;
-use Jifty::Test tests => 12;
+use Jifty::Test tests => 18;
 use Jifty::Test::WWW::Selenium;
 use utf8;
 
@@ -12,33 +12,36 @@
 my $sel    = Jifty::Test::WWW::Selenium->rc_ok($server);
 my $URL    = $server->started_ok;
 
-$sel->open_ok("/1-jifty-update.html");
-
-my $html = $sel->get_html_source;
-
-like $html, qr{<h1>Jifty\.update\(\) tests</h1>}is;
-
-$sel->click_ok("region1");
-sleep 2;
-$html = $sel->get_html_source;
-like $html, qr{<p>Region One</p>}is;
-
-$sel->click_ok("region2");
-sleep 2;
-$html = $sel->get_html_source;
-like $html, qr{<p>Region Two</p>}is;
-
-
-# Update the same region path with different argument
-$sel->click_ok("region3");
-sleep 2;
-$html = $sel->get_html_source;
-like $html, qr{<p>Hello, John</p>}is;
-
-$sel->click_ok("region4");
-sleep 2;
-$html = $sel->get_html_source;
-like $html, qr{<p>Hello, Smith</p>}is;
+{
+    $sel->open_ok("/1-jifty-update.html");
+    $sel->wait_for_text_present_ok("Jifty.update() tests");
+
+    $sel->click_ok("region1");
+    $sel->wait_for_text_present_ok("Region One");
+
+    $sel->click_ok("region2");
+    $sel->wait_for_text_present_ok("Region Two");
+
+    # Update the same region path with different argument
+    $sel->click_ok("region3");
+    $sel->wait_for_text_present_ok("Hello, John");
+
+    $sel->click_ok("region4");
+    $sel->wait_for_text_present_ok("Hello, Smith");
+}
+
+{
+    # One click updates 3 regions, and triggers an alert.
+
+    $sel->open_ok('/region/multiupdate');
+    $sel->click_ok('update');
+    $sel->get_alert_ok();
+
+    $sel->wait_for_text_present_ok("Region One");
+    $sel->wait_for_text_present_ok("Region Two");
+    $sel->wait_for_text_present_ok("Hello, Pony");
+}
 
 $sel->stop;
 
+

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/3-continuation.t
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/3-continuation.t	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,72 @@
+# Test simple continuation using the example in Jifty::Manual::Continuation
+
+use strict;
+use warnings;
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 24;
+use Jifty::Test::WWW::Selenium;
+use utf8;
+
+my $server = Jifty::Test->make_server;
+my $sel    = Jifty::Test::WWW::Selenium->rc_ok($server);
+my $URL    = $server->started_ok;
+
+{
+    # /c/page1 -> /c/page2 -> /c/page1
+
+
+    $sel->open_ok("/c/page1");
+    $sel->wait_for_text_present_ok('first_number');
+
+    my $field = '//input[contains(@class, "text")]';
+    my $button = '//input[@type="submit"]';
+
+    $sel->wait_for_element_present_ok($field);
+    $sel->click_ok($field);
+    $sel->type_ok($field, "100");
+
+    $sel->do_command_ok("clickAndWait", $button);
+
+    my $loc = $sel->get_location;
+    like $loc, qr{/c/page2}, "URL looks like /c/page2";;
+
+    $sel->click_ok($field);
+    $sel->type_ok($field, "50");
+    $sel->do_command_ok("clickAndWait", $button);
+
+    $loc = $sel->get_location;
+    like $loc, qr{/c/page1}, "URL looks like /c/page1";
+
+}
+
+
+{
+    # /c/page_another_one -> /c/page2 -> /c/page_another_one
+
+    $sel->open_ok("/c/page_another_one");
+    $sel->wait_for_text_present_ok('first_number');
+
+    my $field = '//input[contains(@class, "text")]';
+    my $button = '//input[@type="submit"]';
+
+    $sel->wait_for_element_present_ok($field);
+    $sel->click_ok($field);
+    $sel->type_ok($field, "100");
+
+    $sel->do_command_ok("clickAndWait", $button);
+
+    my $loc = $sel->get_location;
+    like $loc, qr{/c/page2}, "URL looks like /c/page2";
+
+    $sel->click_ok($field);
+    $sel->type_ok($field, "50");
+    $sel->do_command_ok("clickAndWait", $button);
+
+    $loc = $sel->get_location;
+    like $loc, qr{/c/page_another_one}, "URL looks like /c/page_another_one";
+}
+
+
+
+$sel->stop;

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/4-tangent.t
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/4-tangent.t	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,45 @@
+# Test tangent / return
+
+use strict;
+use warnings;
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 17;
+use Jifty::Test::WWW::Selenium;
+use utf8;
+
+my $server = Jifty::Test->make_server;
+my $sel    = Jifty::Test::WWW::Selenium->rc_ok($server);
+my $URL    = $server->started_ok;
+
+{
+    # /tangent/page1 -- tangent --> /tangent/returner -- return --> /tangent/page1
+
+    $sel->open_ok("/tangent/page1");
+    $sel->do_command_ok("clickAndWait", "to-returner");
+    like $sel->get_location, qr{/tangent/returner}, "URL looks like /tangent/returner";
+    $sel->do_command_ok("clickAndWait", "returner");
+    like $sel->get_location, qr{/tangent/page1}, "URL looks like /tangent/page1";
+}
+
+{
+    # /tangent/page2 -- tangent --> /tangent/returner -- return --> /tangent/page2
+
+    $sel->open_ok("/tangent/page2");
+    $sel->do_command_ok("clickAndWait", "to-returner");
+    like $sel->get_location, qr{/tangent/returner}, "URL looks like /tangent/returner";
+    $sel->do_command_ok("clickAndWait", "returner");
+    like $sel->get_location, qr{/tangent/page2}, "URL looks like /tangent/page2j";
+}
+
+{
+    # /tangent/page3 -- hyperlink --> /tangent/returner -- return --> /
+
+    $sel->open_ok("/tangent/page3");
+    $sel->do_command_ok("clickAndWait", "to-returner");
+    like $sel->get_location, qr{/tangent/returner}, "URL looks like /tangent/returner";
+    $sel->do_command_ok("clickAndWait", "returner");
+    like $sel->get_location, qr{/}, "URL looks like /";
+}
+
+$sel->stop;

Added: jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/5-action.t
==============================================================================
--- (empty file)
+++ jifty/branches/cssquery-refactor/t/TestApp-JiftyJS/t/5-action.t	Thu Dec 20 04:16:08 2007
@@ -0,0 +1,47 @@
+# Test Action
+
+use strict;
+use warnings;
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 10;
+use Jifty::Test::WWW::Selenium;
+use utf8;
+
+my $server = Jifty::Test->make_server;
+my $sel    = Jifty::Test::WWW::Selenium->rc_ok($server);
+my $URL    = $server->started_ok;
+
+{
+    # Test "Play" action's parameter.
+
+    $sel->open_ok("/act/play");
+
+    my $tags = '//input[contains(@class, "argument-tags")]';
+    my $mood = '//input[contains(@class, "argument-mood")]';
+
+    # Tag is ajax canonicalized to lowercase.
+
+    $sel->set_speed(1000);
+    $sel->click_ok($tags);
+    $sel->type_ok($tags, "FOO");
+    $sel->fire_event($tags, "blur");
+
+    my $tag_value = $sel->get_value($tags);
+    is $tag_value, 'foo', "Tags are canonicalized to lower-case";
+
+    $sel->type_ok($mood, "FOO");
+    $sel->fire_event($tags, "blur");
+    is($sel->get_text('//span[contains(@class, "error text argument-mood")]'),
+       "That doesn't look like a correct value",
+       "mood validation error");
+
+    $sel->type_ok($mood, "angry");
+    $sel->fire_event($tags, "blur");
+    is($sel->get_text('//span[contains(@class, "error text argument-mood")]'),
+       "",
+       "mood validation ok");
+
+}
+
+$sel->stop;

Modified: jifty/branches/cssquery-refactor/t/TestApp/lib/TestApp/Dispatcher.pm
==============================================================================
--- jifty/branches/cssquery-refactor/t/TestApp/lib/TestApp/Dispatcher.pm	(original)
+++ jifty/branches/cssquery-refactor/t/TestApp/lib/TestApp/Dispatcher.pm	Thu Dec 20 04:16:08 2007
@@ -1,6 +1,16 @@
 package TestApp::Dispatcher;
 use Jifty::Dispatcher -base;
 
+under '/' => run {
+}
+
+on '/' => run {
+    # shouldn't ever run because 02-dispatch.t doesn't request the root
+    # demonstrates bad interaction between under '/' and on '/' and 
+    # the condition cache in the dispatcher
+    set phantom => 99;
+}
+
 before '/redirect' => run {
     Jifty->web->request->add_action(
         moniker => 'thing',
@@ -9,8 +19,6 @@
     redirect '/index.html';
 };
 
-
-
 on '/dispatch/' => run {
     dispatch "/dispatch/basic";
 };
@@ -19,12 +27,12 @@
     dispatch "/dispatch/basic-show";
 };
 
-
 my $count = 0;
 my $before = 0;
 my $after = 0;
 my $after_once = 0;
 
+
 on '/dispatch/basic' => run {
     set count => $count++;
 };

Modified: jifty/branches/cssquery-refactor/t/TestApp/t/02-dispatch.t
==============================================================================
--- jifty/branches/cssquery-refactor/t/TestApp/t/02-dispatch.t	(original)
+++ jifty/branches/cssquery-refactor/t/TestApp/t/02-dispatch.t	Thu Dec 20 04:16:08 2007
@@ -4,7 +4,7 @@
 
 use lib 't/lib';
 use Jifty::SubTest;
-use Jifty::Test tests => 28;
+use Jifty::Test tests => 29;
 use Jifty::Test::WWW::Mechanize;
 
 my $server  = Jifty::Test->make_server;
@@ -20,6 +20,7 @@
 $mech->content_contains("before: 0");
 $mech->content_contains("after: 0");
 $mech->content_contains("after_once: 0");
+$mech->content_lacks("phantom: 99");
 
 $mech->get_ok("$URL/dispatch/basic-show", "Got /dispatch/basic-show");
 $mech->content_contains("Basic test with forced show.");


More information about the Jifty-commit mailing list