[Rt-commit] rt branch, 4.2/web-attachs-processing, created. rt-4.1.8-157-g4beb08c

Ruslan Zakirov ruz at bestpractical.com
Wed Apr 17 18:27:21 EDT 2013


The branch, 4.2/web-attachs-processing has been created
        at  4beb08c823d0025668f3413134551323af405d12 (commit)

- Log -----------------------------------------------------------------
commit 14aab28481043f9eafc9282399f57257f3b8b6f3
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jan 22 03:15:04 2011 +0300

    correct indentation in SelfService/Display.html

diff --git a/share/html/SelfService/Display.html b/share/html/SelfService/Display.html
index 25b8ae5..f10caae 100644
--- a/share/html/SelfService/Display.html
+++ b/share/html/SelfService/Display.html
@@ -96,9 +96,7 @@ my @id = ( ref $id eq 'ARRAY' ) ? @{$id} : ($id);
 
 my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
 
-if ( defined ($id[0]) && $id[0] eq 'new' ) {
-
-    # {{{ Create a new ticket
+if ( ($id[0]||'') eq 'new' ) {
 
     my $Queue = RT::Queue->new( $session{'CurrentUser'} );
     unless ( $Queue->Load( $ARGS{'Queue'} ) ) {
@@ -119,15 +117,15 @@ if ( defined ($id[0]) && $id[0] eq 'new' ) {
 
     unless ( $Ticket->id ) {
         $m->comp( 'Error.html', Why => join( "\n", @results ));
-              $m->abort();
-        }
+        $m->abort();
+    }
+}
+else {
+    unless ( $Ticket->Load( $id[0] ) ) {
+        $m->comp( 'Error.html',
+            Why => loc( "Couldn't load ticket '[_1]'", $id ) );
+        $m->abort();
     }
-    else {
-        unless ( $Ticket->Load( $id[0] ) ) {
-            $m->comp( 'Error.html',
-                Why => loc( "Couldn't load ticket '[_1]'", $id ) );
-            $m->abort();
-        }
 
     my ( $code, $msg );
 
@@ -162,31 +160,31 @@ if ( defined ($id[0]) && $id[0] eq 'new' ) {
     }
 
 
-    }
+}
 
-    # This code does automatic redirection if any updates happen.
+# This code does automatic redirection if any updates happen.
 
-    unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
-        $m->comp( 'Error.html',
-            Why => loc("No permission to display that ticket") );
-        # XXX: Why abort? then we loose footer //ruz
-        $m->abort();
-    }
+unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
+    $m->comp( 'Error.html',
+        Why => loc("No permission to display that ticket") );
+    # XXX: Why abort? then we loose footer //ruz
+    $m->abort();
+}
 
-    if (@results) {
-        # We've done something, so we need to clear the decks to avoid
-        # resubmission on refresh.
-        # But we need to store Actions somewhere too, so we don't lose them.
-        my $key = Digest::MD5::md5_hex(rand(1024));
-        push @{ $session{"Actions"}->{$key}  ||= [] }, @results;
-        $session{'i'}++;
-        RT::Interface::Web::Redirect( RT->Config->Get('WebURL') ."SelfService/Display.html?id=". $Ticket->id."&results=".$key);
-    }
+if (@results) {
+    # We've done something, so we need to clear the decks to avoid
+    # resubmission on refresh.
+    # But we need to store Actions somewhere too, so we don't lose them.
+    my $key = Digest::MD5::md5_hex(rand(1024));
+    push @{ $session{"Actions"}->{$key}  ||= [] }, @results;
+    $session{'i'}++;
+    RT::Interface::Web::Redirect( RT->Config->Get('WebURL') ."SelfService/Display.html?id=". $Ticket->id."&results=".$key);
+}
 
-    my $LinkBasicsTitle = $Ticket->CurrentUserHasRight('ModifyTicket')
-                          || $Ticket->CurrentUserHasRight('ReplyToTicket');
-    my $title_box_link = RT->Config->Get('WebPath')."/SelfService/Update.html?id=".$Ticket->Id;
-    $m->callback(CallbackName => 'BeforeDisplay', Ticket => \$Ticket, ARGSRef => \%ARGS, title_box_link => \$title_box_link);
+my $LinkBasicsTitle = $Ticket->CurrentUserHasRight('ModifyTicket')
+                      || $Ticket->CurrentUserHasRight('ReplyToTicket');
+my $title_box_link = RT->Config->Get('WebPath')."/SelfService/Update.html?id=".$Ticket->Id;
+$m->callback(CallbackName => 'BeforeDisplay', Ticket => \$Ticket, ARGSRef => \%ARGS, title_box_link => \$title_box_link);
 </%INIT>
 
 

commit c95aa6090301b49c29d56619b643d98736a1b20d
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jan 22 03:26:30 2011 +0300

    use may be redirect in SelfService

diff --git a/share/html/SelfService/Display.html b/share/html/SelfService/Display.html
index f10caae..8f46467 100644
--- a/share/html/SelfService/Display.html
+++ b/share/html/SelfService/Display.html
@@ -171,15 +171,11 @@ unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
     $m->abort();
 }
 
-if (@results) {
-    # We've done something, so we need to clear the decks to avoid
-    # resubmission on refresh.
-    # But we need to store Actions somewhere too, so we don't lose them.
-    my $key = Digest::MD5::md5_hex(rand(1024));
-    push @{ $session{"Actions"}->{$key}  ||= [] }, @results;
-    $session{'i'}++;
-    RT::Interface::Web::Redirect( RT->Config->Get('WebURL') ."SelfService/Display.html?id=". $Ticket->id."&results=".$key);
-}
+MaybeRedirectForResults(
+    Actions   => \@results,
+    Path      => '/SelfService/Display.html',
+    Arguments => { 'id' => $Ticket->id },
+);
 
 my $LinkBasicsTitle = $Ticket->CurrentUserHasRight('ModifyTicket')
                       || $Ticket->CurrentUserHasRight('ReplyToTicket');

commit c80785470fd0fb234565a0bfff675a840696f02c
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jan 22 16:05:59 2011 +0300

    switch over Abort() instead of manual $m->abort

diff --git a/share/html/SelfService/Display.html b/share/html/SelfService/Display.html
index 8f46467..77c6d21 100644
--- a/share/html/SelfService/Display.html
+++ b/share/html/SelfService/Display.html
@@ -100,15 +100,11 @@ if ( ($id[0]||'') eq 'new' ) {
 
     my $Queue = RT::Queue->new( $session{'CurrentUser'} );
     unless ( $Queue->Load( $ARGS{'Queue'} ) ) {
-        $m->comp( 'Error.html', Why => loc('Queue not found') );
-        $m->abort;
+        Abort( loc('Queue not found') );
     }
 
     unless ( $Queue->CurrentUserHasRight('CreateTicket') ) {
-        $m->comp( 'Error.html',
-            Why =>
-              loc('You have no permission to create tickets in that queue.') );
-        $m->abort;
+        Abort( loc('You have no permission to create tickets in that queue.') );
     }
 
 
@@ -116,15 +112,12 @@ if ( ($id[0]||'') eq 'new' ) {
     CreateTicket( Attachments => delete $session{'Attachments'}, %ARGS );
 
     unless ( $Ticket->id ) {
-        $m->comp( 'Error.html', Why => join( "\n", @results ));
-        $m->abort();
+        Abort( join "\n", @results );
     }
 }
 else {
     unless ( $Ticket->Load( $id[0] ) ) {
-        $m->comp( 'Error.html',
-            Why => loc( "Couldn't load ticket '[_1]'", $id ) );
-        $m->abort();
+        Abort( loc( "Couldn't load ticket '[_1]'", $id ) );
     }
 
     my ( $code, $msg );
@@ -165,10 +158,7 @@ else {
 # This code does automatic redirection if any updates happen.
 
 unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
-    $m->comp( 'Error.html',
-        Why => loc("No permission to display that ticket") );
-    # XXX: Why abort? then we loose footer //ruz
-    $m->abort();
+    Abort( loc("No permission to display that ticket") );
 }
 
 MaybeRedirectForResults(

commit 457ddefa23270e75e81c6eaf87a704298296a912
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 4 11:36:00 2011 +0300

    name a few forms to easier test writing

diff --git a/share/html/SelfService/Create.html b/share/html/SelfService/Create.html
index 7aceec4..a54cc69 100644
--- a/share/html/SelfService/Create.html
+++ b/share/html/SelfService/Create.html
@@ -48,7 +48,7 @@
 <& Elements/Header, Title => loc("Create a ticket") &>
 
 <& /Elements/ListActions, actions => \@results &>
-<form action="Create.html" method="post" enctype="multipart/form-data">
+<form action="Create.html" method="post" enctype="multipart/form-data" name="TicketCreate">
 <input type="hidden" class="hidden" name="id" value="new" />
 
 <table width="100%">
diff --git a/share/html/SelfService/Update.html b/share/html/SelfService/Update.html
index b7dac5b..0e7b4fb 100644
--- a/share/html/SelfService/Update.html
+++ b/share/html/SelfService/Update.html
@@ -51,7 +51,7 @@
 
 % $m->callback(CallbackName => 'BeforeForm', %ARGS, ARGSRef => \%ARGS, Ticket => $Ticket );
 
-<form action="Update.html" method="post" enctype="multipart/form-data">
+<form action="Update.html" method="post" enctype="multipart/form-data" name="TicketUpdate">
 <input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{QuoteTransaction}||'' %>" />
 <input type="hidden" class="hidden" name="UpdateType" value="response" />
 <input type="hidden" class="hidden" name="id" value="<%$Ticket->Id%>" />

commit 1effc562ee1affccf0b35a9c2a3ea8b85d3ce619
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 4 11:39:02 2011 +0300

    get rid of unint warning (self service hits the case)

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index c3d228b..ba8a8f8 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -2015,7 +2015,7 @@ sub ProcessUpdateMessage {
         return;
     }
 
-    if ( $args{ARGSRef}->{'UpdateSubject'} eq ($args{'TicketObj'}->Subject || '') ) {
+    if ( ($args{ARGSRef}->{'UpdateSubject'}||'') eq ($args{'TicketObj'}->Subject || '') ) {
         $args{ARGSRef}->{'UpdateSubject'} = undef;
     }
 

commit af674916f5c4f28c81c0bba1c0d662cf6370e7cd
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Mar 30 18:40:51 2013 +0400

    ProcessAttachments in RT::Interface::Web
    
    * shrink code
    * move some of repeated code into CreateTicket
      and ProcessUpdateMessage

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index ba8a8f8..124c4e1 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -1862,18 +1862,21 @@ sub CreateTicket {
         Interface => RT::Interface::Web::MobileClient() ? 'Mobile' : 'Web',
     );
 
-    if ( $ARGS{'Attachments'} ) {
-        my $rv = $MIMEObj->make_multipart;
-        $RT::Logger->error("Couldn't make multipart message")
-            if !$rv || $rv !~ /^(?:DONE|ALREADY)$/;
+    my @attachments;
+    if ( my $tmp = $session{'Attachments'} ) {
+        push @attachments, grep $_, values %$tmp;
 
-        foreach ( values %{ $ARGS{'Attachments'} } ) {
-            unless ($_) {
-                $RT::Logger->error("Couldn't add empty attachemnt");
-                next;
-            }
-            $MIMEObj->add_part($_);
-        }
+        delete $session{'Attachments'}
+            unless $ARGS{'KeepAttachments'};
+        $session{'Attachments'} = $session{'Attachments'}
+            if @attachments;
+    }
+    if ( $ARGS{'Attachments'} ) {
+        push @attachments, grep $_, values %{ $ARGS{'Attachments'} };
+    }
+    if ( @attachments ) {
+        $MIMEObj->make_multipart;
+        $MIMEObj->add_part( $_ ) foreach @attachments;
     }
 
     for my $argument (qw(Encrypt Sign)) {
@@ -1989,10 +1992,17 @@ sub ProcessUpdateMessage {
         @_
     );
 
-    if ( $args{ARGSRef}->{'UpdateAttachments'}
-        && !keys %{ $args{ARGSRef}->{'UpdateAttachments'} } )
-    {
-        delete $args{ARGSRef}->{'UpdateAttachments'};
+    my @attachments;
+    if ( my $tmp = $session{'Attachments'} ) {
+        push @attachments, grep $_, values %$tmp;
+
+        delete $session{'Attachments'}
+            unless $args{'KeepAttachments'};
+        $session{'Attachments'} = $session{'Attachments'}
+            if @attachments;
+    }
+    if ( $args{ARGSRef}{'UpdateAttachments'} ) {
+        push @attachments, grep $_, values %{ $args{ARGSRef}{'UpdateAttachments'} };
     }
 
     # Strip the signature
@@ -2006,7 +2016,7 @@ sub ProcessUpdateMessage {
     # If, after stripping the signature, we have no message, move the
     # UpdateTimeWorked into adjusted TimeWorked, so that a later
     # ProcessBasics can deal -- then bail out.
-    if (    not $args{ARGSRef}->{'UpdateAttachments'}
+    if (    not @attachments
         and not length $args{ARGSRef}->{'UpdateContent'} )
     {
         if ( $args{ARGSRef}->{'UpdateTimeWorked'} ) {
@@ -2043,9 +2053,9 @@ sub ProcessUpdateMessage {
         );
     }
 
-    if ( $args{ARGSRef}->{'UpdateAttachments'} ) {
+    if ( @attachments ) {
         $Message->make_multipart;
-        $Message->add_part($_) foreach values %{ $args{ARGSRef}->{'UpdateAttachments'} };
+        $Message->add_part( $_ ) foreach @attachments;
     }
 
     if ( $args{ARGSRef}->{'AttachTickets'} ) {
@@ -2138,30 +2148,29 @@ sub ProcessAttachments {
         @_
     );
 
-    my $ARGSRef = $args{ARGSRef} || {};
+    my $update_session = 0;
+
     # deal with deleting uploaded attachments
-    foreach my $key ( keys %$ARGSRef ) {
-        if ( $key =~ m/^DeleteAttach-(.+)$/ ) {
-            delete $session{'Attachments'}{$1};
-        }
-        $session{'Attachments'} = { %{ $session{'Attachments'} || {} } };
+    if ( my $del = $args{'ARGSRef'}{'DeleteAttach'} ) {
+        delete $session{'Attachments'}{ $_ }
+            foreach ref $del? @$del : ($del);
+
+        $update_session = 1;
     }
 
     # store the uploaded attachment in session
-    if ( defined $ARGSRef->{'Attach'} && length $ARGSRef->{'Attach'} )
-    {    # attachment?
-        my $attachment = MakeMIMEEntity( AttachmentFieldName => 'Attach' );
+    my $new = $args{'ARGSRef'}{'Attach'};
+    if ( defined $new && length $new ) {
+        my $attachment = MakeMIMEEntity(
+            AttachmentFieldName => 'Attach'
+        );
 
-        my $file_path = Encode::decode_utf8("$ARGSRef->{'Attach'}");
-        $session{'Attachments'} =
-          { %{ $session{'Attachments'} || {} }, $file_path => $attachment, };
-    }
+        my $file_path = Encode::decode_utf8("$new");
+        $session{'Attachments'}{ $file_path } = $attachment;
 
-    # delete temporary storage entry to make WebUI clean
-    unless ( keys %{ $session{'Attachments'} } and $ARGSRef->{'UpdateAttach'} )
-    {
-        delete $session{'Attachments'};
+        $update_session = 1;
     }
+    $session{'Attachments'} = $session{'Attachments'} if $update_session;
 }
 
 
diff --git a/share/html/Search/Bulk.html b/share/html/Search/Bulk.html
index 14e3720..5484c75 100644
--- a/share/html/Search/Bulk.html
+++ b/share/html/Search/Bulk.html
@@ -276,9 +276,6 @@ my %queues;
 $Tickets->RedoSearch();
 
 unless ( $ARGS{'AddMoreAttach'} ) {
-    # Add session attachments if any to be processed by ProcessUpdateMessage
-    $ARGS{'UpdateAttachments'} = $session{'Attachments'} if ( $session{'Attachments'} );
-
     while ( my $Ticket = $Tickets->Next ) {
         next unless ( $ARGS{ "UpdateTicket" . $Ticket->Id } );
 
@@ -287,9 +284,10 @@ unless ( $ARGS{'AddMoreAttach'} ) {
         $queues{ $Ticket->QueueObj->Id }++;
 
         my @updateresults = ProcessUpdateMessage(
-                TicketObj => $Ticket,
-                ARGSRef   => \%ARGS,
-            );
+            TicketObj       => $Ticket,
+            ARGSRef         => \%ARGS,
+            KeepAttachments => 1,
+        );
 
         #Update the basics.
         my @basicresults =
@@ -359,7 +357,6 @@ unless ( $ARGS{'AddMoreAttach'} ) {
         @results = ( @results, @tempresults );
     }
 
-    # Cleanup WebUI
     delete $session{'Attachments'};
 }
 
diff --git a/share/html/SelfService/Display.html b/share/html/SelfService/Display.html
index 77c6d21..81ffadf 100644
--- a/share/html/SelfService/Display.html
+++ b/share/html/SelfService/Display.html
@@ -96,6 +96,8 @@ my @id = ( ref $id eq 'ARRAY' ) ? @{$id} : ($id);
 
 my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
 
+ProcessAttachments( ARGSRef => \%ARGS );
+
 if ( ($id[0]||'') eq 'new' ) {
 
     my $Queue = RT::Queue->new( $session{'CurrentUser'} );
@@ -108,8 +110,7 @@ if ( ($id[0]||'') eq 'new' ) {
     }
 
 
-    ( $Ticket, @results ) =
-    CreateTicket( Attachments => delete $session{'Attachments'}, %ARGS );
+    ( $Ticket, @results ) = CreateTicket( %ARGS );
 
     unless ( $Ticket->id ) {
         Abort( join "\n", @results );
@@ -120,39 +121,23 @@ else {
         Abort( loc( "Couldn't load ticket '[_1]'", $id ) );
     }
 
-    my ( $code, $msg );
-
-
-    if (
-        $session{'Attachments'}
-        || ( defined $ARGS{'UpdateContent'}
-            && $ARGS{'UpdateContent'} ne ''
-            && $ARGS{'UpdateContent'} ne "-- \n"
-            . $session{'CurrentUser'}->UserObj->Signature )
-      )
-    {
-        $ARGS{UpdateAttachments} = $session{'Attachments'};
-    }
     push @results, ProcessUpdateMessage(
         ARGSRef   => \%ARGS,
         TicketObj => $Ticket
     );
-    delete $session{'Attachments'};
 
     my @cfupdates = ProcessObjectCustomFieldUpdates(Object => $Ticket, ARGSRef => \%ARGS);
     push (@results, @cfupdates);
 
-
     #Update the status
     if (    ( defined $ARGS{'Status'} )
         and $ARGS{'Status'}
         and ( $ARGS{'Status'} ne $Ticket->Status ) )
     {
-        ( $code, $msg ) = $Ticket->SetStatus( $ARGS{'Status'} );
+        my ($code, $msg) = $Ticket->SetStatus( $ARGS{'Status'} );
         push @results, "$msg";
     }
 
-
 }
 
 # This code does automatic redirection if any updates happen.
diff --git a/share/html/Ticket/Display.html b/share/html/Ticket/Display.html
index 205f637..2711549 100644
--- a/share/html/Ticket/Display.html
+++ b/share/html/Ticket/Display.html
@@ -132,10 +132,7 @@ if ($ARGS{'id'} eq 'new') {
         Abort('You have no permission to create tickets in that queue.');
     }
 
-    ($TicketObj, @Actions) = CreateTicket(
-        Attachments => delete $session{'Attachments'},
-        %ARGS,
-    );
+    ($TicketObj, @Actions) = CreateTicket( %ARGS );
     unless ( $TicketObj->CurrentUserHasRight('ShowTicket') ) {
         Abort("No permission to view newly created ticket #".$TicketObj->id.".");
     }
@@ -165,14 +162,11 @@ if ($ARGS{'id'} eq 'new') {
                 ARGSRef => \%ARGS, 
                 Actions => \@Actions);
         
-        $ARGS{UpdateAttachments} = $session{'Attachments'};
-        push @Actions,
-            ProcessUpdateMessage(
+        push @Actions, ProcessUpdateMessage(
             ARGSRef   => \%ARGS,
             Actions   => \@Actions,
             TicketObj => $TicketObj,
-            );
-        delete $session{'Attachments'};
+        );
 
         #Process status updates
         push @Actions, ProcessTicketWatchers(ARGSRef => \%ARGS, TicketObj => $TicketObj );
diff --git a/share/html/Ticket/Elements/AddAttachments b/share/html/Ticket/Elements/AddAttachments
index eefa38b..55a693d 100644
--- a/share/html/Ticket/Elements/AddAttachments
+++ b/share/html/Ticket/Elements/AddAttachments
@@ -45,13 +45,13 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-% if (exists $session{'Attachments'}) {
+% if ( $attachments ) {
 <tr><td class="label"><&|/l&>Attached file</&>:</td>
 <td>
 <&|/l&>Check box to delete</&><br />
-% foreach my $attach_name (keys %{$session{'Attachments'}}) {
-<input type="checkbox" class="checkbox" id="DeleteAttach-<%$attach_name%>" name="DeleteAttach-<%$attach_name%>" value="1" />
-<label for="DeleteAttach-<%$attach_name%>"><%$attach_name%></label>
+% foreach my $attach_name ( keys %$attachments ) {
+<input type="checkbox" class="checkbox" name="DeleteAttach" value="<% $attach_name %>" id="DeleteAttach-<%$attach_name%>" />
+<label for="DeleteAttach-<%$attach_name%>"><% $attach_name %></label>
 <br />
 % } # end of foreach
 </td>
@@ -61,3 +61,9 @@
 <tr><td class="label"><&|/l&>Attach</&>:</td><td><input name="Attach" type="file" /><input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" /><input type="hidden" class="hidden" name="UpdateAttach" value="1" />
 </td></tr>
 % $m->callback( %ARGS, CallbackName => 'End' );
+<%INIT>
+my $attachments;
+if ( exists $session{'Attachments'} && keys %{ $session{'Attachments'} } ) {
+    $attachments = $session{'Attachments'};
+}
+</%INIT>
diff --git a/share/html/Ticket/ModifyAll.html b/share/html/Ticket/ModifyAll.html
index 76e030c..9ff7b38 100644
--- a/share/html/Ticket/ModifyAll.html
+++ b/share/html/Ticket/ModifyAll.html
@@ -183,13 +183,7 @@ unless ($skip_update or $OnlySearchForPeople or $OnlySearchForGroup or $ARGS{'Ad
     push @results, ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS);
     push @results, ProcessObjectCustomFieldUpdates( Object => $Ticket, ARGSRef => \%ARGS);
     push @results, ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS);
-    
-    # Add session attachments if any to be processed by ProcessUpdateMessage
-    $ARGS{'UpdateAttachments'} = $session{'Attachments'} if ( $session{'Attachments'} );
     push @results, ProcessUpdateMessage( TicketObj => $Ticket, ARGSRef=>\%ARGS );
-    # Cleanup WebUI
-    delete $session{'Attachments'};
-
     push @results, ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS );
     push @results, ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
 
diff --git a/share/html/m/ticket/create b/share/html/m/ticket/create
index dee114e..81a309c 100644
--- a/share/html/m/ticket/create
+++ b/share/html/m/ticket/create
@@ -302,14 +302,14 @@ $showrows->(
     &>
 <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj &>
 
-% if (exists $session{'Attachments'}) {
+% if ( my $attachments = $session{'Attachments'} ) {
 
 <%loc("Attached file") %>
 
 <%loc("Check box to delete")%><br />
-% foreach my $attach_name (keys %{$session{'Attachments'}}) {
-<input type="checkbox" class="checkbox" id="DeleteAttach-<%$attach_name%>" name="DeleteAttach-<%$attach_name%>" value="1" />
-<label for="DeleteAttach-<%$attach_name%>"><%$attach_name%></label><br />
+% foreach my $attach_name ( keys %$attachments ) {
+<input type="checkbox" class="checkbox" name="DeleteAttach" value="<% $attach_name %>" id="DeleteAttach-<% $attach_name %>" />
+<label for="DeleteAttach-<% $attach_name %>"><% $attach_name %></label><br />
 % } # end of foreach
 
 
diff --git a/share/html/m/ticket/show b/share/html/m/ticket/show
index d8d5bc2..480664e 100644
--- a/share/html/m/ticket/show
+++ b/share/html/m/ticket/show
@@ -69,10 +69,7 @@ if ($ARGS{'id'} eq 'new') {
         Abort('You have no permission to create tickets in that queue.');
     }
 
-    ($Ticket, @Actions) = CreateTicket(
-        Attachments => delete $session{'Attachments'},
-        %ARGS,
-    );
+    ($Ticket, @Actions) = CreateTicket( %ARGS );
     unless ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
         Abort("No permission to view newly created ticket #".$Ticket->id.".");
     }
@@ -95,14 +92,12 @@ if ($ARGS{'id'} eq 'new') {
             ARGSRef => \%ARGS, 
             Actions => \@Actions);
     
-    $ARGS{UpdateAttachments} = $session{'Attachments'};
     push @Actions,
         ProcessUpdateMessage(
         ARGSRef   => \%ARGS,
         Actions   => \@Actions,
         TicketObj => $Ticket,
         );
-    delete $session{'Attachments'};
 
     #Process status updates
     push @Actions, ProcessTicketWatchers(ARGSRef => \%ARGS, TicketObj => $Ticket );

commit 9a091245912d884daf8f81be5ec72a539e878c10
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Mar 30 22:22:25 2013 +0400

    add token to action pages to differ them
    
    allows us to isolate attachments from different
    actions, so people can do multiple things at the
    same time in different browser's windows.

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 124c4e1..1c18b85 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -1486,7 +1486,7 @@ sub ExpandCSRFToken {
     if ($data->{attach}) {
         my $filename = $data->{attach}{filename};
         my $mime     = $data->{attach}{mime};
-        $HTML::Mason::Commands::session{'Attachments'}{$filename}
+        $HTML::Mason::Commands::session{'Attachments'}{$ARGS->{'Token'}||''}{$filename}
             = $mime;
     }
 
@@ -1863,10 +1863,10 @@ sub CreateTicket {
     );
 
     my @attachments;
-    if ( my $tmp = $session{'Attachments'} ) {
+    if ( my $tmp = $session{'Attachments'}{ $ARGS{'Token'} || '' } ) {
         push @attachments, grep $_, values %$tmp;
 
-        delete $session{'Attachments'}
+        delete $session{'Attachments'}{ $ARGS{'Token'} || '' }
             unless $ARGS{'KeepAttachments'};
         $session{'Attachments'} = $session{'Attachments'}
             if @attachments;
@@ -1993,10 +1993,10 @@ sub ProcessUpdateMessage {
     );
 
     my @attachments;
-    if ( my $tmp = $session{'Attachments'} ) {
+    if ( my $tmp = $session{'Attachments'}{ $args{'ARGSRef'}{'Token'} || '' } ) {
         push @attachments, grep $_, values %$tmp;
 
-        delete $session{'Attachments'}
+        delete $session{'Attachments'}{ $args{'ARGSRef'}{'Token'} || '' }
             unless $args{'KeepAttachments'};
         $session{'Attachments'} = $session{'Attachments'}
             if @attachments;
@@ -2145,14 +2145,17 @@ sub _ProcessUpdateMessageRecipients {
 sub ProcessAttachments {
     my %args = (
         ARGSRef => {},
+        Token   => '',
         @_
     );
 
+    my $token = $args{'Token'};
+
     my $update_session = 0;
 
     # deal with deleting uploaded attachments
     if ( my $del = $args{'ARGSRef'}{'DeleteAttach'} ) {
-        delete $session{'Attachments'}{ $_ }
+        delete $session{'Attachments'}{ $token }{ $_ }
             foreach ref $del? @$del : ($del);
 
         $update_session = 1;
@@ -2166,7 +2169,7 @@ sub ProcessAttachments {
         );
 
         my $file_path = Encode::decode_utf8("$new");
-        $session{'Attachments'}{ $file_path } = $attachment;
+        $session{'Attachments'}{ $token }{ $file_path } = $attachment;
 
         $update_session = 1;
     }
diff --git a/share/html/Search/Bulk.html b/share/html/Search/Bulk.html
index 5484c75..c62b3ea 100644
--- a/share/html/Search/Bulk.html
+++ b/share/html/Search/Bulk.html
@@ -50,7 +50,7 @@
 
 <& /Elements/ListActions, actions => \@results &>
 <form method="post" action="<% RT->Config->Get('WebPath') %>/Search/Bulk.html" enctype="multipart/form-data" name="BulkUpdate" id="BulkUpdate">
-% foreach my $var (qw(Query Format OrderBy Order Rows Page SavedChartSearchId)) {
+% foreach my $var (qw(Query Format OrderBy Order Rows Page SavedChartSearchId Token)) {
 <input type="hidden" class="hidden" name="<%$var%>" value="<%$ARGS{$var} || ''%>" />
 %}
 <& /Elements/CollectionList, 
@@ -226,7 +226,8 @@ map ( $ARGS{$_} =~ /^$/ && ( delete $ARGS{$_} ), keys %ARGS );
 
 my (@results);
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 $Page ||= 1;
 
@@ -357,7 +358,7 @@ unless ( $ARGS{'AddMoreAttach'} ) {
         @results = ( @results, @tempresults );
     }
 
-    delete $session{'Attachments'};
+    delete $session{'Attachments'}{ $Token };
 }
 
 my $TxnCFs = RT::CustomFields->new( $session{CurrentUser} );
@@ -366,6 +367,7 @@ $TxnCFs->LimitToGlobalOrObjectId( sort keys %queues );
 
 </%INIT>
 <%args>
+$Token => undef
 $Format => undef
 $Page => 1
 $Rows => undef
diff --git a/share/html/SelfService/Create.html b/share/html/SelfService/Create.html
index a54cc69..99dc112 100644
--- a/share/html/SelfService/Create.html
+++ b/share/html/SelfService/Create.html
@@ -50,6 +50,7 @@
 <& /Elements/ListActions, actions => \@results &>
 <form action="Create.html" method="post" enctype="multipart/form-data" name="TicketCreate">
 <input type="hidden" class="hidden" name="id" value="new" />
+<input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
 
 <table width="100%">
 <tr>
@@ -111,6 +112,7 @@
 
 </form>
 <%args>
+$Token => undef
 $Queue => undef
 </%args>
 <%init>
@@ -118,7 +120,8 @@ my @results;
 my $queue_obj = RT::Queue->new($session{'CurrentUser'});
 $queue_obj->Load($Queue);
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 my $skip_create = 0;
 
diff --git a/share/html/SelfService/Display.html b/share/html/SelfService/Display.html
index 81ffadf..5e90375 100644
--- a/share/html/SelfService/Display.html
+++ b/share/html/SelfService/Display.html
@@ -96,8 +96,6 @@ my @id = ( ref $id eq 'ARRAY' ) ? @{$id} : ($id);
 
 my $Ticket = RT::Ticket->new( $session{'CurrentUser'} );
 
-ProcessAttachments( ARGSRef => \%ARGS );
-
 if ( ($id[0]||'') eq 'new' ) {
 
     my $Queue = RT::Queue->new( $session{'CurrentUser'} );
diff --git a/share/html/SelfService/Update.html b/share/html/SelfService/Update.html
index 0e7b4fb..cddd3bd 100644
--- a/share/html/SelfService/Update.html
+++ b/share/html/SelfService/Update.html
@@ -55,6 +55,7 @@
 <input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{QuoteTransaction}||'' %>" />
 <input type="hidden" class="hidden" name="UpdateType" value="response" />
 <input type="hidden" class="hidden" name="id" value="<%$Ticket->Id%>" />
+<input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
 <table width="100%">
     <tr>
         <td class="label">
@@ -112,7 +113,8 @@ Abort( loc("No permission to view update ticket") )
   unless ( $Ticket->CurrentUserHasRight('ReplyToTicket')
     or $Ticket->CurrentUserHasRight('ModifyTicket') );
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 if ( exists $ARGS{SubmitTicket} ) {
     $m->callback(CallbackName => 'BeforeDisplay', Ticket => \$Ticket, ARGSRef => \%ARGS);
@@ -123,5 +125,6 @@ if ( exists $ARGS{SubmitTicket} ) {
 <%ARGS>
 $id => undef
 $Action => undef
+$Token => undef
 $DefaultStatus => undef
 </%ARGS>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index 9b123bc..d108019 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -54,6 +54,7 @@
 
 <form action="<% RT->Config->Get('WebPath') %>/Ticket/Create.html" method="post" enctype="multipart/form-data" name="TicketCreate">
   <input type="hidden" class="hidden" name="id" value="new" />
+  <input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
   
 % $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 
@@ -374,7 +375,8 @@ $QueueObj->Disabled && Abort(loc("Cannot create tickets in a disabled queue."));
 
 my $ticket = RT::Ticket->new($session{'CurrentUser'}); # empty ticket object
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 my $checks_failure = 0;
 
@@ -441,6 +443,7 @@ PageMenu->child( details => raw_html =>  q[<a href="#details" onclick="return sw
 </%INIT>
 
 <%ARGS>
+$Token => undef
 $DependsOn => undef
 $DependedOnBy => undef
 $MemberOf => undef
diff --git a/share/html/Ticket/Elements/AddAttachments b/share/html/Ticket/Elements/AddAttachments
index 55a693d..d86ef5b 100644
--- a/share/html/Ticket/Elements/AddAttachments
+++ b/share/html/Ticket/Elements/AddAttachments
@@ -61,9 +61,12 @@
 <tr><td class="label"><&|/l&>Attach</&>:</td><td><input name="Attach" type="file" /><input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" /><input type="hidden" class="hidden" name="UpdateAttach" value="1" />
 </td></tr>
 % $m->callback( %ARGS, CallbackName => 'End' );
+<%ARGS>
+$Token => ''
+</%ARGS>
 <%INIT>
 my $attachments;
-if ( exists $session{'Attachments'} && keys %{ $session{'Attachments'} } ) {
-    $attachments = $session{'Attachments'};
+if ( exists $session{'Attachments'}{ $Token } && keys %{ $session{'Attachments'}{ $Token } } ) {
+    $attachments = $session{'Attachments'}{ $Token };
 }
 </%INIT>
diff --git a/share/html/Ticket/ModifyAll.html b/share/html/Ticket/ModifyAll.html
index 9ff7b38..3fb5192 100644
--- a/share/html/Ticket/ModifyAll.html
+++ b/share/html/Ticket/ModifyAll.html
@@ -54,6 +54,7 @@
 <form method="post" action="ModifyAll.html" name="TicketModifyAll" enctype="multipart/form-data">
 % $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS );
 <input type="hidden" class="hidden" name="id" value="<%$Ticket->Id%>" />
+<input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
 
 <&| /Widgets/TitleBox, title => loc('Modify ticket # [_1]', $Ticket->Id), class=>'ticket-info-basics' &>
 <& Elements/EditBasics, TicketObj => $Ticket, defaults => \%ARGS &>
@@ -146,7 +147,8 @@ $CanRespond = 1 if ( $Ticket->CurrentUserHasRight('ReplyToTicket') or
 $CanComment = 1 if ( $Ticket->CurrentUserHasRight('CommentOnTicket') or
                      $Ticket->CurrentUserHasRight('ModifyTicket') );
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 my @results;
 my $skip_update = 0;
@@ -211,6 +213,7 @@ unless ($Ticket->CurrentUserHasRight('ShowTicket')) {
 
 
 <%ARGS>
+$Token => undef
 $OnlySearchForPeople => undef
 $OnlySearchForGroup => undef
 $UserField => undef
diff --git a/share/html/Ticket/Update.html b/share/html/Ticket/Update.html
index 3f1274e..319ac46 100644
--- a/share/html/Ticket/Update.html
+++ b/share/html/Ticket/Update.html
@@ -57,6 +57,7 @@
 <input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{QuoteTransaction}||'' %>" />
 <input type="hidden" class="hidden" name="DefaultStatus" value="<% $DefaultStatus ||''%>" />
 <input type="hidden" class="hidden" name="Action" value="<% $ARGS{Action}||'' %>" />
+<input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
 
 <& /Elements/GnuPG/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
 
@@ -240,8 +241,9 @@ $CanRespond = 1 if ( $TicketObj->CurrentUserHasRight('ReplyToTicket') or
 $CanComment = 1 if ( $TicketObj->CurrentUserHasRight('CommentOnTicket') or
                      $TicketObj->CurrentUserHasRight('ModifyTicket') ); 
 
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
 
-ProcessAttachments(ARGSRef => \%ARGS);
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 my $gnupg_widget = $m->comp('/Elements/GnuPG/SignEncryptWidget:new', Arguments => \%ARGS );
 $m->comp( '/Elements/GnuPG/SignEncryptWidget:Process',
@@ -300,4 +302,5 @@ if ( !$checks_failure && !$skip_update && exists $ARGS{SubmitTicket} ) {
 $id => undef
 $Action => undef
 $DefaultStatus => undef
+$Token => undef
 </%ARGS>
diff --git a/share/html/m/ticket/create b/share/html/m/ticket/create
index 81a309c..b4e4606 100644
--- a/share/html/m/ticket/create
+++ b/share/html/m/ticket/create
@@ -46,6 +46,7 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <%ARGS>
+$Token => ''
 $QuoteTransaction => undef
 $CloneTicket => undef
 </%ARGS>
@@ -146,7 +147,8 @@ $m->callback( QueueObj => $QueueObj, title => \$title, results => \@results, ARG
 
 $QueueObj->Disabled && Abort(loc("Cannot create tickets in a disabled queue."));
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 my $checks_failure = 0;
 
@@ -214,6 +216,7 @@ if ((!exists $ARGS{'AddMoreAttach'}) and (defined($ARGS{'id'}) and $ARGS{'id'} e
 <& /Elements/ListActions, actions => \@results  &>
 <form action="<% RT->Config->Get('WebPath') %>/m/ticket/create" method="post" enctype="multipart/form-data" name="TicketCreate" id="ticket-create">
 <input type="hidden" class="hidden" name="id" value="new" />
+<input type="hidden" class="hidden" name="Token" value="<% $Token %>" />
 % $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 % if ($gnupg_widget) {
 <& /Elements/GnuPG/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
@@ -302,7 +305,7 @@ $showrows->(
     &>
 <& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj &>
 
-% if ( my $attachments = $session{'Attachments'} ) {
+% if ( my $attachments = $session{'Attachments'}{'Token'}) {
 
 <%loc("Attached file") %>
 
diff --git a/share/html/m/ticket/reply b/share/html/m/ticket/reply
index 0a1bec2..61ff499 100644
--- a/share/html/m/ticket/reply
+++ b/share/html/m/ticket/reply
@@ -194,7 +194,8 @@ $CanRespond = 1 if ( $t->CurrentUserHasRight('ReplyToTicket') or
 $CanComment = 1 if ( $t->CurrentUserHasRight('CommentOnTicket') or
                      $t->CurrentUserHasRight('ModifyTicket') ); 
 
-ProcessAttachments(ARGSRef => \%ARGS);
+$ARGS{'Token'} ||= $Token ||= Digest::MD5::md5_hex( rand(1024) );
+ProcessAttachments( ARGSRef => \%ARGS, Token => $Token );
 
 # check email addresses for RT's
 {
@@ -235,6 +236,7 @@ if ( !$checks_failure && !$skip_update && exists $ARGS{SubmitTicket} ) {
 
 <%ARGS>
 $id => undef
+$Token => ''
 $Action => 'Respond'
 $DefaultStatus => undef
 </%ARGS>

commit 4beb08c823d0025668f3413134551323af405d12
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 4 11:39:51 2011 +0300

    more tests to cover attachments uploading through the web UI

diff --git a/lib/RT/Test.pm b/lib/RT/Test.pm
index 97ab94a..aec3a0e 100644
--- a/lib/RT/Test.pm
+++ b/lib/RT/Test.pm
@@ -806,7 +806,10 @@ sub create_ticket {
     my $self = shift;
     my %args = @_;
 
-    if ($args{Queue} && $args{Queue} =~ /\D/) {
+    if ( blessed $args{'Queue'} ) {
+        $args{Queue} = $args{'Queue'}->id;
+    }
+    elsif ($args{Queue} && $args{Queue} =~ /\D/) {
         my $queue = RT::Queue->new(RT->SystemUser);
         if (my $id = $queue->Load($args{Queue}) ) {
             $args{Queue} = $id;
diff --git a/t/web/attachments.t b/t/web/attachments.t
index ba5c712..316396d 100644
--- a/t/web/attachments.t
+++ b/t/web/attachments.t
@@ -1,94 +1,505 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 33;
+use RT::Test tests => 159;
 
 use constant LogoFile => $RT::StaticPath .'/images/bpslogo.png';
 use constant FaviconFile => $RT::StaticPath .'/images/favicon.png';
 use constant TextFile => $RT::MasonComponentRoot .'/NoAuth/css/print.css';
 
-my ($baseurl, $m) = RT::Test->started_ok;
+my ($url, $m) = RT::Test->started_ok;
 ok $m->login, 'logged in';
 
-my $queue = RT::Queue->new(RT->Nobody);
-my $qid = $queue->Load('General');
-ok( $qid, "Loaded General queue" );
-
-$m->form_name('CreateTicketInQueue');
-$m->field('Queue', $qid);
-$m->submit;
-is($m->status, 200, "request successful");
-$m->content_contains("Create a new ticket", 'ticket create page');
-
-$m->form_name('TicketCreate');
-$m->field('Subject', 'Attachments test');
-$m->field('Attach',  LogoFile);
-$m->field('Content', 'Some content');
-$m->submit;
-is($m->status, 200, "request successful");
-
-$m->content_contains('Attachments test', 'we have subject on the page');
-$m->content_contains('Some content', 'and content');
-$m->content_contains('Download bpslogo.png', 'page has file name');
-
-open LOGO, "<", LogoFile or die "Can't open logo file: $!";
-binmode LOGO;
-my $logo_contents = do {local $/; <LOGO>};
-close LOGO;
-$m->follow_link_ok({text => "Download bpslogo.png"});
-is($m->content_type, "image/png");
-is($m->content, $logo_contents, "Binary content matches");
-
-$m->back;
-$m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
-$m->form_name('TicketUpdate');
-$m->field('Attach',  TextFile);
-$m->click('AddMoreAttach');
-is($m->status, 200, "request successful");
-
-$m->form_name('TicketUpdate');
-$m->field('Attach',  FaviconFile);
-$m->field('UpdateContent', 'Message');
-$m->click('SubmitTicket');
-is($m->status, 200, "request successful");
-
-$m->content_contains('Download bpslogo.png', 'page has file name');
-$m->content_contains('Download favicon.png', 'page has file name');
-$m->content_contains('Download print.css', 'page has file name');
-
-$m->follow_link_ok( { text => 'Download bpslogo.png' } );
-is( $m->response->header('Content-Type'), 'image/png', 'Content-Type of png lacks charset' );
-
-$m->back;
-
-$m->follow_link_ok( { text => 'Download print.css' } );
-is( $m->response->header('Content-Type'),
-    'text/css;charset=UTF-8', 'Content-Type of text has charset' );
-
-diag "test mobile ui";
-$m->get_ok( $baseurl . '/m/ticket/create?Queue=' . $qid );
-
-$m->form_name('TicketCreate');
-$m->field('Subject', 'Attachments test');
-$m->field('Attach',  LogoFile);
-$m->field('Content', 'Some content');
-$m->submit;
-is($m->status, 200, "request successful");
-
-$m->content_contains('Attachments test', 'we have subject on the page');
-$m->content_contains('bpslogo.png', 'page has file name');
-
-$m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
-$m->form_name('TicketUpdate');
-$m->field('Attach',  LogoFile);
-$m->click('AddMoreAttach');
-is($m->status, 200, "request successful");
-
-$m->form_name('TicketUpdate');
-$m->field('Attach',  FaviconFile);
-$m->field('UpdateContent', 'Message');
-$m->click('SubmitTicket');
-is($m->status, 200, "request successful");
-
-$m->content_contains('bpslogo.png', 'page has file name');
-$m->content_contains('favicon.png', 'page has file name');
+my $queue = RT::Test->load_or_create_queue( Name => 'General' );
+ok( $queue && $queue->id, "Loaded General queue" );
+
+diag "create a ticket in full interface";
+diag "w/o attachments";
+{
+    $m->goto_create_ticket( $queue );
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->content_contains("Create a new ticket", 'ticket create page');
+    $m->submit;
+    is($m->status, 200, "request successful");
+}
+
+diag "with one attachment";
+{
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Subject', 'Attachments test');
+    $m->field('Attach',  LogoFile);
+    $m->field('Content', 'Some content');
+
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('Some content', 'and content');
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+}
+
+diag "with two attachments";
+{
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('Subject', 'Attachments test');
+    $m->field('Content', 'Some content');
+
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('Some content', 'and content');
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "with one attachment, but delete one along the way";
+{
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  FaviconFile);
+    $m->tick( 'DeleteAttach', LogoFile );
+    $m->field('Subject', 'Attachments test');
+    $m->field('Content', 'Some content');
+
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('Some content', 'and content');
+    $m->content_lacks('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "with one attachment, but delete one along the way";
+{
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->tick( 'DeleteAttach', LogoFile );
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  FaviconFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->field('Subject', 'Attachments test');
+    $m->field('Content', 'Some content');
+
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('Some content', 'and content');
+    $m->content_lacks('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "reply to a ticket in full interface";
+diag "with one attachment";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+}
+
+diag "with two attachments";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "with one attachment, delete one along the way";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketUpdate');
+    $m->tick('DeleteAttach',  LogoFile);
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->content_lacks('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "jumbo interface";
+diag "with one attachment";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Jumbo'}, "jumbo the ticket");
+    $m->form_name('TicketModifyAll');
+    $m->field('Attach',  LogoFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->goto_ticket( $ticket->id );
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+}
+
+diag "with two attachments";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Jumbo'}, "jumbo the ticket");
+    $m->form_name('TicketModifyAll');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketModifyAll');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->goto_ticket( $ticket->id );
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "with one attachment, delete one along the way";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->goto_ticket( $ticket->id );
+    $m->follow_link_ok({text => 'Jumbo'}, "jumbo the ticket");
+    $m->form_name('TicketModifyAll');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketModifyAll');
+    $m->tick('DeleteAttach',  LogoFile);
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->goto_ticket( $ticket->id );
+    $m->content_lacks('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "bulk update";
+diag "one attachment";
+{
+    my @tickets = RT::Test->create_tickets(
+        {
+            Queue   => $queue,
+            Subject => 'Attachments test',
+            Content => 'Some content',
+        },
+        {},
+        {},
+    );
+    my $query = join ' OR ', map "id=$_", map $_->id, @tickets;
+    $query =~ s/ /%20/g;
+    $m->get_ok( $url . "/Search/Bulk.html?Query=$query&Rows=10" );
+
+    $m->form_name('BulkUpdate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    foreach my $ticket ( @tickets ) {
+        $m->goto_ticket( $ticket->id );
+        $m->content_lacks('Download bpslogo.png', 'page has file name');
+        $m->content_contains('Download favicon.png', 'page has file name');
+    }
+}
+
+diag "two attachments";
+{
+    my @tickets = RT::Test->create_tickets(
+        {
+            Queue   => $queue,
+            Subject => 'Attachments test',
+            Content => 'Some content',
+        },
+        {},
+        {},
+    );
+    my $query = join ' OR ', map "id=$_", map $_->id, @tickets;
+    $query =~ s/ /%20/g;
+    $m->get_ok( $url . "/Search/Bulk.html?Query=$query&Rows=10" );
+
+    $m->form_name('BulkUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('BulkUpdate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    foreach my $ticket ( @tickets ) {
+        $m->goto_ticket( $ticket->id );
+        $m->content_contains('Download bpslogo.png', 'page has file name');
+        $m->content_contains('Download favicon.png', 'page has file name');
+    }
+}
+
+diag "one attachment, delete one along the way";
+{
+    my @tickets = RT::Test->create_tickets(
+        {
+            Queue   => $queue,
+            Subject => 'Attachments test',
+            Content => 'Some content',
+        },
+        {},
+        {},
+    );
+    my $query = join ' OR ', map "id=$_", map $_->id, @tickets;
+    $query =~ s/ /%20/g;
+    $m->get_ok( $url . "/Search/Bulk.html?Query=$query&Rows=10" );
+
+    $m->form_name('BulkUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('BulkUpdate');
+    $m->tick('DeleteAttach',  LogoFile);
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    foreach my $ticket ( @tickets ) {
+        $m->goto_ticket( $ticket->id );
+        $m->content_lacks('Download bpslogo.png', 'page has file name');
+        $m->content_contains('Download favicon.png', 'page has file name');
+    }
+}
+
+diag "self service";
+diag "create with attachment";
+{
+    $m->get_ok( $url . "/SelfService/Create.html?Queue=". $queue->id );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('Content', 'Message');
+    ok($m->current_form->find_input('AddMoreAttach'), "more than one attachment");
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "update with attachment";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m->get_ok( $url . "/SelfService/Update.html?id=". $ticket->id );
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    ok($m->current_form->find_input('AddMoreAttach'), "more than one attachment");
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Download favicon.png', 'page has file name');
+}
+
+diag "mobile ui";
+
+diag "simple create + reply";
+{
+    $m->get_ok( $url . '/m/ticket/create?Queue=' . $queue->id );
+
+    $m->form_name('TicketCreate');
+    $m->field('Subject', 'Attachments test');
+    $m->field('Attach',  LogoFile);
+    $m->field('Content', 'Some content');
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('bpslogo.png', 'page has file name');
+
+    $m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketUpdate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('UpdateContent', 'Message');
+    $m->click('SubmitTicket');
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('bpslogo.png', 'page has file name');
+    $m->content_contains('favicon.png', 'page has file name');
+}
+
+
+diag "check content type and content";
+{
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  LogoFile);
+    $m->click('AddMoreAttach');
+    is($m->status, 200, "request successful");
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  TextFile);
+    $m->field('Subject', 'Attachments test');
+    $m->field('Content', 'Some content');
+
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_contains('Attachments test', 'we have subject on the page');
+    $m->content_contains('Some content', 'and content');
+    $m->content_contains('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download print.css', 'page has file name');
+
+    $m->follow_link_ok({text => "Download bpslogo.png"});
+    is($m->response->header('Content-Type'), 'image/png', 'Content-Type of png lacks charset' );
+    is($m->content_type, "image/png");
+    is($m->content, RT::Test->file_content(LogoFile), "Binary content matches");
+    $m->back;
+
+    $m->follow_link_ok( { text => 'Download print.css' } );
+    is( $m->response->header('Content-Type'),
+        'text/css;charset=UTF-8',
+        'Content-Type of text has charset',
+    );
+    is($m->content_type, "text/css");
+    is($m->content, RT::Test->file_content(TextFile), "Text content matches");
+}
+
+diag "concurent actions";
+my $m2 = RT::Test::Web->new;
+ok $m2->login, 'second login';
+
+diag "update and create";
+{
+    my $ticket = RT::Test->create_ticket(
+        Queue   => $queue,
+        Subject => 'Attachments test',
+        Content => 'Some content',
+    );
+
+    $m2->goto_ticket( $ticket->id );
+    $m2->follow_link_ok({text => 'Reply'}, "reply to the ticket");
+    $m2->form_name('TicketUpdate');
+    $m2->field('Attach',  LogoFile);
+    $m2->click('AddMoreAttach');
+    is($m2->status, 200, "request successful");
+
+    $m->goto_create_ticket( $queue );
+
+    $m->form_name('TicketCreate');
+    $m->field('Attach',  FaviconFile);
+    $m->field('Subject', 'Attachments test');
+    $m->field('Content', 'Some content');
+    $m->submit;
+    is($m->status, 200, "request successful");
+
+    $m->content_lacks('Download bpslogo.png', 'page has file name');
+    $m->content_contains('Download favicon.png', 'page has file name');
+
+    $m2->form_name('TicketUpdate');
+    $m2->click('SubmitTicket');
+    $m2->content_contains('Download bpslogo.png', 'page has file name');
+    $m2->content_lacks('Download favicon.png', 'page has no file name');
+}
+

-----------------------------------------------------------------------


More information about the Rt-commit mailing list