Index: app/controllers/results_controller.rb
===================================================================
--- app/controllers/results_controller.rb	(revision 1078)
+++ app/controllers/results_controller.rb	(working copy)
@@ -1,32 +1,15 @@
 class ResultsController < ApplicationController
-  before_filter      :authorize_only_for_admin, :except => [:codeviewer,
-  :edit, :update_mark, :view_marks, :create, :add_extra_mark, :next_grouping, :update_overall_comment, :expand_criteria, :collapse_criteria, :remove_extra_mark, :expand_unmarked_criteria, :update_marking_state]
-  before_filter      :authorize_for_ta_and_admin, :only => [:edit,
-  :update_mark, :create, :add_extra_mark, :download, :next_grouping, :update_overall_comment, :expand_criteria, :collapse_criteria, :remove_extra_mark, :expand_unmarked_criteria, :update_marking_state]
+  before_filter      :authorize_only_for_admin, :except => [:codeviewer, :edit, :update_mark, :view_marks,
+                        :create, :add_extra_mark, :next_grouping, :update_overall_comment, :expand_criteria,
+                        :collapse_criteria, :remove_extra_mark, :expand_unmarked_criteria, :update_marking_state,
+                        :download]
+  before_filter      :authorize_for_ta_and_admin, :only => [:edit, :update_mark, :create, :add_extra_mark,
+                        :download, :next_grouping, :update_overall_comment, :expand_criteria,
+                        :collapse_criteria, :remove_extra_mark, :expand_unmarked_criteria,
+                        :update_marking_state]
   before_filter      :authorize_for_user, :only => [:codeviewer]
   before_filter      :authorize_for_student, :only => [:view_marks]
 
-  def create
-    # Create new Result for this Submission
-    @submission_id = params[:id]
-    @submission = Submission.find(@submission_id)
-    
-    # Is there already a result for this Submission?
-    if @submission.has_result?
-      # If so, our new Result needs to have a version number greater than the
-      # old result version.  We're also going to set this new result to be current.
-      old_result = @submission.get_result_used
-      old_result.result_version_used = false
-      old_result.save
-    end
-    
-    new_result = Result.new
-    new_result.submission = @submission
-    new_result.marking_state = Result::MARKING_STATES[:partial]
-    new_result.save
-    redirect_to :action => 'edit', :id => new_result.id
-  end
-  
   def index
   end
   
@@ -43,7 +26,7 @@
     @first_file = @files.first
     @extra_marks_points = @result.extra_marks.points
     @extra_marks_percentage = @result.extra_marks.percentage
-    @marks_map = []
+    @marks_map = Hash.new
     @rubric_criteria.each do |criterion|
       mark = Mark.find_or_create_by_result_id_and_rubric_criterion_id(@result.id, criterion.id)
       mark.save(false)
@@ -133,9 +116,11 @@
     @result = @file.submission.result
     # Is the current user a student?
     if current_user.student?
-      # The Student does not have access to this file.  Render nothing.
+      # The Student does not have access to this file. Display an error.
       if @file.submission.grouping.membership_status(current_user).nil?
-        raise "No access to submission file with id #{@submission_file_id}"
+        render :partial => 'shared/handle_error',
+               :locals => {:error => I18n.t('submission_file.error.no_access', :submission_file_id => @submission_file_id)}
+        return
       end
     end
 
@@ -145,9 +130,8 @@
     begin
       @file_contents = retrieve_file(@file)
     rescue Exception => e
-      render :update do |page|
-        page.call "alert", e.message
-      end
+      render :partial => 'shared/handle_error',
+             :locals => {:error => e.message}
       return
     end   
     
@@ -160,18 +144,10 @@
     mark_value = params[:mark]
     result_mark.mark = mark_value
     if !result_mark.save
-      render :update do |page|
-        page.call 'alert', 'Could not save this mark!: ' + result_mark.errors
-      end
+      render :partial => 'shared/handle_error', :locals => {:error => I18n.t('mark.error.save') + result_mark.errors}
     else
-      render :update do |page|
-        page.call 'select_mark', result_mark.id, mark_value
-        page.replace_html "rubric_criterion_title_#{result_mark.id.to_s}_mark", "<b> #{result_mark.mark}:  #{result_mark.rubric_criterion["level_" + result_mark.mark.to_s + "_name"]}</b> #{result_mark.rubric_criterion["level_" + result_mark.mark.to_s + "_description"]}"
-        page.replace_html "mark_#{result_mark.id.to_s}_summary_mark", result_mark.mark
-        page.replace_html "mark_#{result_mark.id.to_s}_summary_mark_after_weight", (result_mark.mark * result_mark.rubric_criterion.weight)
-        page.replace_html "current_subtotal_div", result_mark.result.get_subtotal
-        page.call "update_total_mark", result_mark.result.total_mark
-      end
+      render :partial => 'results/marker/update_mark',
+             :locals => { :result_mark => result_mark, :mark_value => mark_value}
     end
   end
   
@@ -183,7 +159,6 @@
       redirect_to :controller => 'assignments', :action => 'student_interface', :id => params[:id]
       return
     end
-    
     if !@grouping.has_submission?
       render 'results/student/no_submission'
       return
@@ -205,7 +180,7 @@
     @first_file = @files.first
     @extra_marks_points = @result.extra_marks.points
     @extra_marks_percentage = @result.extra_marks.percentage
-    @marks_map = []
+    @marks_map = Hash.new
     @rubric_criteria.each do |criterion|
       mark = Mark.find_or_create_by_result_id_and_rubric_criterion_id(@result.id, criterion.id)
       mark.save(false)
@@ -218,9 +193,8 @@
     if request.post?
       @extra_mark = ExtraMark.new
       @extra_mark.result = @result
-      @extra_mark.update_attributes(params[:extra_mark])
       @extra_mark.unit = ExtraMark::UNITS[:points]
-      if !@extra_mark.save
+      if !@extra_mark.update_attributes(params[:extra_mark])
         render :action => 'results/marker/add_extra_mark_error'
       else
         render :action => 'results/marker/insert_extra_mark'
@@ -240,46 +214,7 @@
     @result = @extra_mark.result
     render :action => 'results/marker/remove_extra_mark'
   end
-
-  #update the mark and/or description of the extra mark
-  def update_extra_mark
-    extra_mark = ExtraMark.find(params[:id])
-    #the attribute to be changed - description or mark
-    type = params[:type]
-    #the new attribute value
-    val = params[:value]
-    #change the value
-    extra_mark[type] = val
-
-    #save it
-    if extra_mark.valid? && extra_mark.save
-      #need to update the total mark
-      result = Result.find(extra_mark.result_id)
-      result.calculate_total
-      render :update do |page|
-        #The following divs need to be changed
-        #1 the display of the extra mark
-        page.replace_html("extra_mark_title_#{extra_mark.id}_" + type, val)
-        #2 the display of the total mark
-        page.replace_html("current_total_mark_div", result.total_mark)
-        #3 the divs containing deductions/bonuses
-        page.replace_html("extra_marks_bonus", result.get_bonus_marks)
-        page.replace_html("extra_marks_deducted", result.get_deductions)
-        #4 the div containing the total mark at the top of the page
-        page.replace_html("current_mark_div", result.total_mark)
-      end
-    else
-      output = {'status' => 'error'}
-      render :json => output.to_json
-    end
-  end
   
-  def update_overall_comment
-    @result = Result.find(params[:id])
-    @result.overall_comment = params[:result][:overall_comment]
-    @result.save
-  end
-  
   def expand_criteria
     @assignment = Assignment.find(params[:aid])
     @rubric_criteria = @assignment.rubric_criteria
Index: app/views/results/common/_annotations.js.erb
===================================================================
--- app/views/results/common/_annotations.js.erb	(revision 1078)
+++ app/views/results/common/_annotations.js.erb	(working copy)
@@ -133,7 +133,7 @@
     return false;
   }
  
-  <%= remote_function (
+  <%= remote_function(
                     :url => { :controller => "annotations", :action => "add_existing_annotation" },
                     :with => "'submission_file_id='+ $('select_file_id').value +'&line_start=' + positions.line_start + '&line_end=' + positions.line_end + '&annotation_text_id='+ annotation_text_id")
                     %>
@@ -151,7 +151,7 @@
   $('loading_code').show();
   $('select_file_id').disable();
   line_annotations = null;
-<%= remote_function (:url =>{ :action => "codeviewer", :id => @assignment.id, :uid => @uid }, :with => "'submission_file_id='+submission_file_id+'&focus_line='+focus_line")%>
+<%= remote_function(:url =>{ :action => "codeviewer", :id => @assignment.id, :uid => @uid }, :with => "'submission_file_id='+submission_file_id+'&focus_line='+focus_line")%>
 }
 
 function load_submitted_file_and_focus(submission_file_id, focus_line) {
@@ -173,7 +173,7 @@
   //Close the dialog
   modal.close();
   //Send AJAX request
-  <%= remote_function (
+  <%= remote_function(
                     :url => { :controller => "annotations", :action => "create" },
                     :with => "'submission_file_id='+ $('select_file_id').value +'&line_start=' + positions.line_start + ' &line_end=' + positions.line_end + '&content=' + encodeURIComponent(content) + '&category_id=' + category_id")
                     %>
Index: app/views/results/marker/_update_mark.rjs
===================================================================
--- app/views/results/marker/_update_mark.rjs	(revision 0)
+++ app/views/results/marker/_update_mark.rjs	(revision 0)
@@ -0,0 +1,6 @@
+page.call 'select_mark', result_mark.id, mark_value
+page.replace_html "rubric_criterion_title_#{result_mark.id.to_s}_mark", "<b> #{result_mark.mark}:  #{result_mark.rubric_criterion["level_" + result_mark.mark.to_s + "_name"]}</b> #{result_mark.rubric_criterion["level_" + result_mark.mark.to_s + "_description"]}"
+page.replace_html "mark_#{result_mark.id.to_s}_summary_mark", result_mark.mark
+page.replace_html "mark_#{result_mark.id.to_s}_summary_mark_after_weight", (result_mark.mark * result_mark.rubric_criterion.weight)
+page.replace_html "current_subtotal_div", result_mark.result.get_subtotal
+page.call "update_total_mark", result_mark.result.total_mark
\ No newline at end of file
Index: app/views/shared/_handle_error.rjs
===================================================================
--- app/views/shared/_handle_error.rjs	(revision 0)
+++ app/views/shared/_handle_error.rjs	(revision 0)
@@ -0,0 +1 @@
+page.call "alert", error
Index: test/functional/groups_controller_test.rb
===================================================================
--- test/functional/groups_controller_test.rb	(revision 1078)
+++ test/functional/groups_controller_test.rb	(working copy)
@@ -138,7 +138,7 @@
         should_render_template 'remove_member.rjs'
         should_assign_to :mbr_id, :assignment, :grouping
         should "assign @inviter accordingly" do
-          assert_nil assigns(:inviter)
+          assert_equal false, assigns(:inviter)
         end
       end
       
@@ -274,7 +274,9 @@
         should_assign_to(:errors) { [] }
         should_render_template 'delete_groupings.rjs'
       end
-      
+     
     end
+  
+  end
 
 end
Index: test/functional/results_controller_test.rb
===================================================================
--- test/functional/results_controller_test.rb	(revision 1078)
+++ test/functional/results_controller_test.rb	(working copy)
@@ -1,8 +1,814 @@
 require File.dirname(__FILE__) + '/authenticated_controller_test'
+require 'shoulda'
+require 'mocha'
 
-class ResultsControllerTest < ActionController::TestCase
-  # Replace this with your real tests.
-  test "the truth" do
-    assert true
-  end
-end
+class ResultsControllerTest < AuthenticatedControllerTest
+  
+  SAMPLE_ERR_MSG = "sample error message"
+  
+  context "An unauthenticated and unauthorized user doing a" do
+    
+    # Since we are not authenticated and authorized, we should be redirected
+    # to the login page
+    
+    context "GET on :index" do
+      setup do
+        get :index, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :edit" do
+      setup do
+        get :edit, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :next_grouping" do
+      setup do
+        get :next_grouping, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :set_released_to_student" do
+      setup do
+        get :set_released_to_student, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :update_marking_state" do
+      setup do
+        get :update_marking_state, :id => 1, :value => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :download" do
+      setup do
+        get :download, :select_file_id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :codeviewer" do
+      setup do
+        get :codeviewer, :id => 1, :submission_file_id => 1, :focus_line => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :update_mark" do
+      setup do
+        get :update_mark, :mark_id => 1, :mark => 0
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :view_marks" do
+      setup do
+        get :view_marks, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :add_extra_mark" do
+      setup do
+        get :add_extra_mark, :id => 1, :extra_mark => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "POST on :add_extra_mark" do
+      setup do
+        post :add_extra_mark, :id => 1, :extra_mark => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :remove_extra_mark" do
+      setup do
+        get :remove_extra_mark, :id => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :expand_criteria" do
+      setup do
+        get :expand_criteria, :aid => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :collapse_criteria" do
+      setup do
+        get :collapse_criteria, :aid => 1
+      end
+      should_respond_with :redirect
+    end
+    
+    context "GET on :expand_unmarked_criteria" do
+      setup do
+        get :expand_unmarked_criteria, :aid => 1, :rid => 1
+      end
+      should_respond_with :redirect
+    end
+    
+  end # unauthenticated and unauthorized user doing
+  
+  context "An authenticated and authorized student doing a" do
+    fixtures :users, :results, :assignments, :marks, :rubric_criteria
+    
+    setup do
+      @student = users(:student1)
+      @assignment = assignments(:assignment_5)
+    end
+    
+    context "GET on :index" do
+      setup do
+        get_as @student, :index, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :edit" do
+      setup do
+        get_as @student, :edit, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :next_grouping" do
+      setup do
+        get_as @student, :next_grouping, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :set_released_to_student" do
+      setup do
+        get_as @student, :set_released_to_student, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :update_marking_state" do
+      setup do
+        get_as @student, :update_marking_state, :id => 1, :value => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :download" do
+      setup do
+        get_as @student, :download, :select_file_id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :codeviewer" do
+      setup do
+       @submission_file = submission_files(:student1_ass_5_sub_1)
+      end
+     
+      context "and the student has no access to that file" do
+        setup do
+          @no_access_submission_file = submission_files(:grouping_2_ass_1_sub_2)
+          get_as @student, :codeviewer, :id => @assignment.id, :submission_file_id => @no_access_submission_file.id, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line
+        should_not_assign_to :file_contents, :annots, :all_annots
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "set an appropriate error message" do
+          # Workaround to assert that the error message made its way to the response
+          r = Regexp.new(I18n.t('submission_file.error.no_access', :submission_file_id => @no_access_submission_file.id))
+          assert_match r, @response.body
+        end
+      end
+      
+      context "with file reading error" do
+        setup do
+          # We simulate a file reading error.
+          ResultsController.any_instance.expects(:retrieve_file).once.raises(Exception.new(SAMPLE_ERR_MSG))
+          get_as @student, :codeviewer, :id => @assignment.id, :submission_file_id => @submission_file.id, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result,
+                         :annots, :all_annots
+        should_not_assign_to :file_contents, :code_type
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "pass along the exception's message" do
+          # Workaround to assert that the error message made its way to the response
+          assert_match Regexp.new(SAMPLE_ERR_MSG), @response.body
+        end
+      end
+      
+      context "without error" do
+        setup do
+          # We don't want to access a real file. 
+          ResultsController.any_instance.expects(:retrieve_file).once.returns('file content')
+          get_as @student, :codeviewer, :id => @assignment.id, :submission_file_id => @submission_file.id, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result,
+                         :annots, :all_annots, :file_contents, :code_type
+        should_render_template 'results/common/codeviewer'
+        should_respond_with :success
+      end
+      
+    end
+    
+    context "GET on :update_mark" do
+      setup do
+        get_as @student, :update_mark, :mark_id => 1, :mark => 0
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :view_marks" do
+      
+      context "and his grouping has no submission" do
+        setup do
+          Grouping.any_instance.expects(:has_submission?).once.returns(false)
+          get_as @student, :view_marks, :id => @assignment.id
+        end
+        should_assign_to :assignment, :grouping
+        should_render_template 'results/student/no_submission'
+        should_respond_with :success
+      end
+    
+      context "and his submission has no result" do
+        setup do
+          Submission.any_instance.expects(:has_result?).once.returns(false)
+          get_as @student, :view_marks, :id => @assignment.id
+        end
+        should_assign_to :assignment, :grouping, :submission
+        should_render_template 'results/student/no_result'
+        should_respond_with :success
+      end
+    
+      context "and the result has not been released" do
+        setup do
+          Result.any_instance.expects(:released_to_students).once.returns(false)
+          get_as @student, :view_marks, :id => @assignment.id
+        end
+        should_assign_to :assignment, :grouping, :submission, :result
+        should_render_template 'results/student/no_result'
+        should_respond_with :success
+      end
+    
+      context "and the result is available" do
+        setup do
+          get_as @student, :view_marks, :id => @assignment.id
+        end
+        should_assign_to :assignment, :grouping, :submission,
+                         :result, :rubric_criteria, :annotation_categories,
+                         :group, :files, :first_file, :extra_marks_points,
+                         :extra_marks_percentage, :marks_map
+        should_respond_with :success
+        should_render_template :view_marks
+      end
+      
+    end
+    
+    context "GET on :add_extra_mark" do
+      setup do
+        get_as @student, :add_extra_mark, :id => 1, :extra_mark => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :remove_extra_mark" do
+      setup do
+        get_as @student, :remove_extra_mark, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :expand_criteria" do
+      setup do
+        get_as @student, :expand_criteria, :aid => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :collapse_criteria" do
+      setup do
+        get_as @student, :collapse_criteria, :aid => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :expand_unmarked_criteria" do
+      setup do
+        get_as @student, :expand_unmarked_criteria, :aid => 1, :rid => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+  end # An authenticated and authorized student doing a
+  
+  context "An authenticated and authorized admin doing a" do
+    fixtures :users, :submissions, :submission_files, :groupings, :results, :annotations, :marks, :extra_marks
+    
+    setup do
+      @admin = users(:olm_admin_1)
+      @submission = submissions(:submission_1)
+      @grouping = groupings(:grouping_1)
+      @assignment = assignments(:assignment_1)
+      @result = results(:result_1)
+      @released_result = results(:result_4)
+      @mark = marks(:mark_1)
+      @extra_mark = extra_marks(:extra_mark_1)
+    end
+    
+    context "GET on :edit" do
+      setup do
+        get_as @admin, :edit, :id => @released_result.id
+      end
+      should_not_set_the_flash 
+      should_render_template :edit
+      should_respond_with :success
+    end
+    
+    context "GET on :next_grouping" do
+      
+      context "when current grouping has submission" do
+        setup do
+          Grouping.any_instance.stubs(:has_submission).returns(true)
+          get_as @admin, :next_grouping, :id => @grouping.id
+        end
+        should_respond_with :redirect
+      end
+      
+      context "when current grouping has no submission" do
+        setup do
+          Grouping.any_instance.stubs(:has_submission).returns(false)
+          get_as @admin, :next_grouping, :id => @grouping.id
+        end
+        should_respond_with :redirect
+      end
+      
+    end
+    
+    context "GET on :set_released_to_students" do
+      setup do
+        get_as @admin, :set_released_to_students, :id => @result.id, :value => 'true'
+      end
+      should_respond_with :success
+      should_assign_to :result
+    end
+    
+    context "GET on :update_marking_state" do
+      setup do
+        get_as @admin, :update_marking_state, :id => @result.id, :marking_state => 'complete'
+      end
+      should_respond_with :success
+      should_assign_to :result
+    end
+    
+    context "GET on :download" do
+      setup do
+        @file = SubmissionFile.new
+      end
+      
+      context "without file error" do
+        setup do
+          @file.expects(:filename).once.returns('filename')
+          SubmissionFile.expects(:find).with('1').returns(@file)
+          ResultsController.any_instance.stubs(:retrieve_file).returns('file content')
+          get_as @admin, :download, :select_file_id => 1
+        end
+        should_not_set_the_flash
+        should_respond_with_content_type "application/octet-stream"
+        should_respond_with :success
+        should "respond with appropriate content" do
+          assert_equal 'file content', @response.body
+        end
+      end
+      
+      context "with file error" do
+        setup do
+          submission = Submission.new
+          submission.expects(:result).once.returns(@result)
+          @file.expects(:submission).once.returns(submission)
+          SubmissionFile.expects(:find).with('1').returns(@file)
+          ResultsController.any_instance.expects(:retrieve_file).once.raises(Exception.new(SAMPLE_ERR_MSG))
+          get_as @admin, :download, :select_file_id => 1
+        end
+        should_set_the_flash_to SAMPLE_ERR_MSG
+        should_respond_with :redirect
+      end
+    end
+    
+    context "GET on :codeviewer" do
+      setup do
+        @file = SubmissionFile.new
+        annotation = Annotation.new
+        SubmissionFile.expects(:find).once.with('1').returns(@file)
+        @file.expects(:submission).twice.returns(@submission)
+        @file.expects(:annotations).once.returns(annotation)
+      end
+      
+      context "without file error" do
+        setup do
+          @file.expects(:get_file_type).once.returns('txt')
+          ResultsController.any_instance.expects(:retrieve_file).once.returns('file content')
+          get_as @admin, :codeviewer, :id => @assignment.id, :submission_file_id => 1, :focus_line => 1
+        end
+        should_not_set_the_flash
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result, :annots, :all_annots, :file_contents, :code_type
+        should_render_template 'results/common/codeviewer'
+        should_respond_with :success
+      end
+      
+      context "with file error" do
+        setup do
+          ResultsController.any_instance.expects(:retrieve_file).once.raises(Exception.new(SAMPLE_ERR_MSG))
+          get_as @admin, :codeviewer, :id => @assignment.id, :submission_file_id => 1, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result, :annots, :all_annots
+        should_not_assign_to :file_contents, :code_type
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "pass along the exception's message" do
+          # Workaround to assert that the error message made its way to the response
+          assert_match Regexp.new(SAMPLE_ERR_MSG), @response.body
+        end
+      end
+    end
+    
+    context "GET on :update_mark" do
+      setup do
+      end
+      
+      context "with save error" do
+        setup do
+          Mark.expects(:find).with('1').returns(@mark)
+          @mark.expects(:save).once.returns(false)
+          @mark.expects(:errors).once.returns(SAMPLE_ERR_MSG)
+          get_as @admin, :update_mark, :mark_id => 1, :mark => 1
+        end
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "pass along the \"error hash\"" do
+          # Workaround to assert that the error message made its way to the response
+          assert_match Regexp.new(SAMPLE_ERR_MSG), @response.body
+        end
+      end
+      
+      context "without save error" do
+        setup do
+          get_as @admin, :update_mark, :mark_id => @mark.id, :mark => 1
+        end
+        should_render_template 'results/marker/_update_mark.rjs'
+        should_respond_with :success
+      end
+      
+    end 
+    
+    context "GET on :view_marks" do
+      setup do
+        get_as @admin, :view_marks, :id => @assignment.id
+      end
+      should_render_template '404'
+      should_respond_with 404
+    end
+    
+    context "GET on :add_extra_mark" do
+      setup do
+        get_as @admin, :add_extra_mark, :id => @result.id
+      end
+      should_assign_to :result
+      should_render_template 'results/marker/add_extra_mark'
+      should_respond_with :success
+    end
+    
+    context "POST on :add_extra_mark" do
+      
+      context "with save error" do
+        setup do
+          extra_mark = ExtraMark.new
+          ExtraMark.expects(:new).once.returns(extra_mark)
+          extra_mark.expects(:save).once.returns(false)
+          post_as @admin, :add_extra_mark, :id => @result.id, :extra_mark => { :extra_mark => 1 }
+        end
+        should_assign_to :result, :extra_mark
+        should_render_template 'results/marker/add_extra_mark_error'
+        should_respond_with :success
+      end
+      
+      context "without save error" do
+        setup do
+          post_as @admin, :add_extra_mark, :id => @result.id, :extra_mark => { :extra_mark => 1 }
+        end
+        should_assign_to :result, :extra_mark
+        should_render_template 'results/marker/insert_extra_mark'
+        should_respond_with :success
+      end
+      
+    end
+
+    context "GET on :remove_extra_mark" do
+      setup do
+        get_as @admin, :remove_extra_mark, :id => @extra_mark.id
+      end
+      should_not_set_the_flash
+      should_assign_to :result
+      should_render_template 'results/marker/remove_extra_mark'
+      should_respond_with :success      
+    end
+    
+    context "GET on :expand_criteria" do
+      setup do
+        get_as @admin, :expand_criteria, :aid => @assignment.id
+      end
+      should_assign_to :assignment, :rubric_criteria
+      should_render_template 'results/marker/_expand_criteria.rjs'
+      should_respond_with :success
+    end
+    
+    context "GET on :collapse_criteria" do
+      setup do
+        get_as @admin, :collapse_criteria, :aid => @assignment.id
+      end
+      should_assign_to :assignment, :rubric_criteria
+      should_render_template 'results/marker/_collapse_criteria.rjs'
+      should_respond_with :success
+    end
+    
+    context "GET on :expand_unmarked_criteria" do
+      setup do
+        get_as @admin, :expand_unmarked_criteria, :aid => @assignment.id, :rid => @result.id        
+      end
+      should_assign_to :assignment, :rubric_criteria, :result, :nil_marks
+      should_render_template 'results/marker/_expand_unmarked_criteria'
+      should_respond_with :success
+    end
+    
+  end # An authenticated and authorized admin doing a
+  
+  context "An authenticated and authorized TA doing a" do
+    fixtures :users
+    
+    setup do
+      @ta = users(:ta3)
+      @submission = submissions(:submission_1)
+      @grouping = groupings(:grouping_1)
+      @assignment = assignments(:assignment_1)
+      @result = results(:result_5)
+      @released_result = results(:result_4)
+      @mark = marks(:mark_1)
+      @extra_mark = extra_marks(:extra_mark_1)
+    end
+    
+    context "GET on :index" do
+      setup do
+        get_as @ta, :index, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :edit" do
+      setup do
+        get_as @ta, :edit, :id => @result.id
+      end
+      should_not_set_the_flash 
+      should_render_template :edit
+      should_respond_with :success
+    end
+    
+    context "GET on :next_grouping" do
+      
+      context "when current grouping has submission" do
+        setup do
+          Grouping.any_instance.stubs(:has_submission).returns(true)
+          get_as @ta, :next_grouping, :id => @grouping.id
+        end
+        should_respond_with :redirect
+      end
+      
+      context "when current grouping has no submission" do
+        setup do
+          Grouping.any_instance.stubs(:has_submission).returns(false)
+          get_as @ta, :next_grouping, :id => @grouping.id
+        end
+        should_respond_with :redirect
+      end
+      
+    end
+    
+    context "GET on :set_released_to_student" do
+      setup do
+        get_as @ta, :set_released_to_student, :id => 1
+      end
+      should_respond_with :missing
+      should_render_template 404
+    end
+    
+    context "GET on :update_marking_state" do
+      setup do
+        get_as @ta, :update_marking_state, :id => @result.id, :marking_state => 'complete'
+      end
+      should_respond_with :success
+      should_assign_to :result
+    end
+    
+    context "GET on :download" do
+      setup do
+        @file = SubmissionFile.new
+      end
+      
+      context "without file error" do
+        setup do
+          @file.expects(:filename).once.returns('filename')
+          SubmissionFile.expects(:find).with('1').returns(@file)
+          ResultsController.any_instance.stubs(:retrieve_file).returns('file content')
+          get_as @ta, :download, :select_file_id => 1
+        end
+        should_not_set_the_flash
+        should_respond_with_content_type "application/octet-stream"
+        should_respond_with :success
+        should "respond with appropriate content" do
+          assert_equal 'file content', @response.body
+        end
+      end
+      
+      context "with file error" do
+        setup do
+          submission = Submission.new
+          submission.expects(:result).once.returns(@result)
+          @file.expects(:submission).once.returns(submission)
+          SubmissionFile.expects(:find).with('1').returns(@file)
+          ResultsController.any_instance.expects(:retrieve_file).once.raises(Exception.new(SAMPLE_ERR_MSG))
+          get_as @ta, :download, :select_file_id => 1
+        end
+        should_set_the_flash_to SAMPLE_ERR_MSG
+        should_respond_with :redirect
+      end
+    end
+    
+    context "GET on :codeviewer" do
+      setup do
+       @submission_file = submission_files(:student1_ass_5_sub_1)
+      end
+      
+      context "with file reading error" do
+        setup do
+          # We simulate a file reading error.
+          ResultsController.any_instance.expects(:retrieve_file).once.raises(Exception.new(SAMPLE_ERR_MSG))
+          get_as @ta, :codeviewer, :id => @assignment.id, :submission_file_id => @submission_file.id, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result,
+                         :annots, :all_annots
+        should_not_assign_to :file_contents, :code_type
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "pass along the exception's message" do
+          # Workaround to assert that the error message made its way to the response
+          assert_match Regexp.new(SAMPLE_ERR_MSG), @response.body
+        end
+      end
+      
+      context "without error" do
+        setup do
+          # We don't want to access a real file. 
+          ResultsController.any_instance.expects(:retrieve_file).once.returns('file content')
+          get_as @ta, :codeviewer, :id => @assignment.id, :submission_file_id => @submission_file.id, :focus_line => 1
+        end
+        should_assign_to :assignment, :submission_file_id, :focus_line, :file, :result,
+                         :annots, :all_annots, :file_contents, :code_type
+        should_render_template 'results/common/codeviewer'
+        should_respond_with :success
+      end
+      
+    end
+    
+    context "GET on :update_mark" do
+      
+      context "with save error" do
+        setup do
+          Mark.expects(:find).with('1').returns(@mark)
+          @mark.expects(:save).once.returns(false)
+          @mark.expects(:errors).once.returns(SAMPLE_ERR_MSG)
+          get_as @ta, :update_mark, :mark_id => 1, :mark => 1
+        end
+        should_render_template 'shared/_handle_error.rjs'
+        should_respond_with :success
+        should "pass along the exception's message" do
+          # Workaround to assert that the error message made its way to the response
+          assert_match Regexp.new(SAMPLE_ERR_MSG), @response.body
+        end
+      end
+      
+      context "without save error" do
+        setup do
+          get_as @ta, :update_mark, :mark_id => @mark.id, :mark => 1
+        end
+        should_render_template 'results/marker/_update_mark.rjs'
+        should_respond_with :success
+      end
+      
+    end 
+    
+    context "GET on :view_marks" do
+      setup do
+        get_as @ta, :view_marks, :id => @assignment.id
+      end
+      should_render_template '404'
+      should_respond_with 404
+    end
+    
+    context "GET on :add_extra_mark" do
+      setup do
+        unmarked_result = results(:result_1)
+        get_as @ta, :add_extra_mark, :id => unmarked_result.id
+      end
+      should_assign_to :result
+      should_render_template 'results/marker/add_extra_mark'
+      should_respond_with :success
+    end
+    
+    context "POST on :add_extra_mark" do
+      setup do
+        @unmarked_result = results(:result_1)
+      end
+      
+      context "with save error" do
+        setup do
+          extra_mark = ExtraMark.new
+          ExtraMark.expects(:new).once.returns(extra_mark)
+          extra_mark.expects(:save).once.returns(false)
+          post_as @ta, :add_extra_mark, :id => @unmarked_result.id, :extra_mark => { :extra_mark => 1 }
+        end
+        should_assign_to :result, :extra_mark
+        should_render_template 'results/marker/add_extra_mark_error'
+        should_respond_with :success
+      end
+      
+      context "without save error" do
+        setup do
+          post_as @ta, :add_extra_mark, :id => @unmarked_result.id, :extra_mark => { :extra_mark => 1 }
+        end
+        should_assign_to :result, :extra_mark
+        should_render_template 'results/marker/insert_extra_mark'
+        should_respond_with :success
+      end
+      
+    end
+    
+    context "GET on :remove_extra_mark" do
+      setup do
+        get_as @ta, :remove_extra_mark, :id => @extra_mark.id
+      end
+      should_not_set_the_flash
+      should_assign_to :result
+      should_render_template 'results/marker/remove_extra_mark'
+      should_respond_with :success      
+    end
+    
+    context "GET on :expand_criteria" do
+      setup do
+        get_as @ta, :expand_criteria, :aid => @assignment.id 
+      end
+      should_assign_to :assignment, :rubric_criteria
+      should_render_template 'results/marker/_expand_criteria.rjs'
+      should_respond_with :success
+    end
+    
+    context "GET on :collapse_criteria" do
+      setup do
+        get_as @ta, :collapse_criteria, :aid => @assignment.id
+      end
+      should_assign_to :assignment, :rubric_criteria
+      should_render_template 'results/marker/_collapse_criteria.rjs'
+      should_respond_with :success
+    end
+    
+    context "GET on :expand_unmarked_criteria" do
+      setup do
+        get_as @ta, :expand_unmarked_criteria, :aid => @assignment.id, :rid => @result.id
+      end
+      should_assign_to :assignment, :rubric_criteria, :result, :nil_marks
+      should_render_template 'results/marker/_expand_unmarked_criteria'
+      should_respond_with :success
+    end
+    
+  end # An authenticated and authorized TA doing a
+  
+end
\ No newline at end of file

