2012-03-28 22:52:21 +08:00
#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require File . expand_path ( File . dirname ( __FILE__ ) + '/../spec_helper.rb' )
describe ContentMigration do
context " course copy " do
before do
2012-04-16 21:31:40 +08:00
course_with_teacher ( :course_name = > " from course " )
2012-03-28 22:52:21 +08:00
@copy_from = @course
2012-04-16 21:31:40 +08:00
course_with_teacher ( :user = > @user , :course_name = > " to course " )
2012-03-28 22:52:21 +08:00
@copy_to = @course
@cm = ContentMigration . new ( :context = > @copy_to , :user = > @user , :source_course = > @copy_from , :copy_options = > { :everything = > " 1 " } )
@cm . save!
end
it " should show correct progress " do
ce = ContentExport . new
2012-04-11 01:16:57 +08:00
ce . export_type = ContentExport :: COMMON_CARTRIDGE
2012-03-28 22:52:21 +08:00
ce . content_migration = @cm
@cm . content_export = ce
ce . save!
@cm . progress . should == nil
@cm . workflow_state = 'exporting'
ce . progress = 10
@cm . progress . should == 4
ce . progress = 50
@cm . progress . should == 20
ce . progress = 75
@cm . progress . should == 30
ce . progress = 100
@cm . progress . should == 40
@cm . progress = 10
@cm . progress . should == 46
@cm . progress = 50
@cm . progress . should == 70
@cm . progress = 80
@cm . progress . should == 88
@cm . progress = 100
@cm . progress . should == 100
end
def run_course_copy
@cm . copy_course_without_send_later
@cm . reload
@cm . warnings . should == [ ]
if @cm . migration_settings [ :last_error ]
er = ErrorReport . last
" #{ er . message } - #{ er . backtrace } " . should == " "
end
@cm . workflow_state . should == 'imported'
@copy_to . reload
end
it " should migrate syllabus links on copy " do
course_model
topic = @copy_from . discussion_topics . create! ( :title = > " some topic " , :message = > " <p>some text</p> " )
@copy_from . syllabus_body = " <a href='/courses/ #{ @copy_from . id } /discussion_topics/ #{ topic . id } '>link</a> "
@copy_from . save!
run_course_copy
new_topic = @copy_to . discussion_topics . find_by_migration_id ( CC :: CCHelper . create_key ( topic ) )
new_topic . should_not be_nil
new_topic . message . should == topic . message
@copy_to . syllabus_body . should match ( / \/ courses \/ #{ @copy_to . id } \/ discussion_topics \/ #{ new_topic . id } / )
end
2012-04-16 21:31:40 +08:00
it " should copy course attributes " do
@copy_from . tab_configuration = [ { " id " = > 0 } , { " id " = > 14 } , { " id " = > 8 } , { " id " = > 5 } , { " id " = > 6 } , { " id " = > 2 } , { " id " = > 3 , " hidden " = > true } ]
@copy_from . locale = " es "
@copy_from . save
run_course_copy
@copy_to . locale . should == 'es'
@copy_to . tab_configuration . should == @copy_from . tab_configuration
@copy_to . name . should == @copy_from . name
end
2012-03-28 22:52:21 +08:00
it " should copy external tools " do
tool_from = @copy_from . context_external_tools . create! ( :name = > " new tool " , :consumer_key = > " key " , :shared_secret = > " secret " , :domain = > 'example.com' , :custom_fields = > { 'a' = > '1' , 'b' = > '2' } )
tool_from . settings [ :course_navigation ] = { :url = > " http://www.example.com " , :text = > " Example URL " }
tool_from . save
run_course_copy
@copy_to . context_external_tools . count . should == 1
tool_to = @copy_to . context_external_tools . first
tool_to . name . should == tool_from . name
tool_to . custom_fields . should == tool_from . custom_fields
tool_to . has_course_navigation . should == true
tool_to . consumer_key . should == tool_from . consumer_key
tool_to . shared_secret . should == tool_from . shared_secret
end
it " should not duplicate external tools used in modules " do
tool_from = @copy_from . context_external_tools . create! ( :name = > " new tool " , :consumer_key = > " key " , :shared_secret = > " secret " , :domain = > 'example.com' , :custom_fields = > { 'a' = > '1' , 'b' = > '2' } )
tool_from . settings [ :course_navigation ] = { :url = > " http://www.example.com " , :text = > " Example URL " }
tool_from . save
mod1 = @copy_from . context_modules . create! ( :name = > " some module " )
tag = mod1 . add_item ( { :type = > 'context_external_tool' ,
:title = > 'Example URL' ,
:url = > " http://www.example.com " ,
:new_tab = > true } )
tag . save
run_course_copy
@copy_to . context_external_tools . count . should == 1
tool_to = @copy_to . context_external_tools . first
tool_to . name . should == tool_from . name
tool_to . consumer_key . should == tool_from . consumer_key
tool_to . has_course_navigation . should == true
end
it " should copy external tool assignments " do
assignment_model ( :course = > @copy_from , :points_possible = > 40 , :submission_types = > 'external_tool' , :grading_type = > 'points' )
tag_from = @assignment . build_external_tool_tag ( :url = > " http://example.com/one " , :new_tab = > true )
tag_from . content_type = 'ContextExternalTool'
tag_from . save!
run_course_copy
asmnt_2 = @copy_to . assignments . first
asmnt_2 . submission_types . should == " external_tool "
asmnt_2 . external_tool_tag . should_not be_nil
tag_to = asmnt_2 . external_tool_tag
tag_to . content_type . should == tag_from . content_type
tag_to . url . should == tag_from . url
tag_to . new_tab . should == tag_from . new_tab
end
def mig_id ( obj )
CC :: CCHelper . create_key ( obj )
end
it " should merge locked files and retain correct html links " do
att = Attachment . create! ( :filename = > 'test.txt' , :display_name = > " testing.txt " , :uploaded_data = > StringIO . new ( 'file' ) , :folder = > Folder . root_folders ( @copy_from ) . first , :context = > @copy_from )
att . update_attribute ( :hidden , true )
att . reload . should be_hidden
topic = @copy_from . discussion_topics . create! ( :title = > " some topic " , :message = > " <img src='/courses/ #{ @copy_from . id } /files/ #{ att . id } /preview'> " )
run_course_copy
new_att = @copy_to . attachments . find_by_migration_id ( CC :: CCHelper . create_key ( att ) )
new_att . should_not be_nil
new_topic = @copy_to . discussion_topics . find_by_migration_id ( CC :: CCHelper . create_key ( topic ) )
new_topic . should_not be_nil
new_topic . message . should match ( Regexp . new ( " /courses/ #{ @copy_to . id } /files/ #{ new_att . id } /preview " ) )
end
it " should selectively copy items " do
dt1 = @copy_from . discussion_topics . create! ( :message = > " hi " , :title = > " discussion title " )
dt2 = @copy_from . discussion_topics . create! ( :message = > " hey " , :title = > " discussion title 2 " )
dt3 = @copy_from . announcements . create! ( :message = > " howdy " , :title = > " announcement title " )
cm = @copy_from . context_modules . create! ( :name = > " some module " )
cm2 = @copy_from . context_modules . create! ( :name = > " another module " )
att = Attachment . create! ( :filename = > 'first.txt' , :uploaded_data = > StringIO . new ( 'ohai' ) , :folder = > Folder . unfiled_folder ( @copy_from ) , :context = > @copy_from )
att2 = Attachment . create! ( :filename = > 'second.txt' , :uploaded_data = > StringIO . new ( 'ohai' ) , :folder = > Folder . unfiled_folder ( @copy_from ) , :context = > @copy_from )
wiki = @copy_from . wiki . wiki_pages . create! ( :title = > " wiki " , :body = > " ohai " )
wiki2 = @copy_from . wiki . wiki_pages . create! ( :title = > " wiki2 " , :body = > " ohais " )
2012-04-16 22:27:33 +08:00
data = [ { :points = > 3 , :description = > " Outcome row " , :id = > 1 , :ratings = > [ { :points = > 3 , :description = > " Rockin' " , :criterion_id = > 1 , :id = > 2 } ] } ]
rub1 = @copy_from . rubrics . build ( :title = > " rub1 " )
rub1 . data = data
rub1 . save!
rub2 = @copy_from . rubrics . build ( :title = > " rub2 " )
rub1 . data = data
rub1 . save!
default = LearningOutcomeGroup . default_for ( @copy_from )
lo = @copy_from . learning_outcomes . new
lo . context = @copy_from
lo . short_description = " outcome1 "
lo . workflow_state = 'active'
lo . data = { :rubric_criterion = > { :mastery_points = > 2 , :ratings = > [ { :description = > " e " , :points = > 50 } , { :description = > " me " , :points = > 2 } , { :description = > " Does Not Meet Expectations " , :points = > 0 . 5 } ] , :description = > " First outcome " , :points_possible = > 5 } }
lo . save!
lo2 = @copy_from . learning_outcomes . new
lo2 . context = @copy_from
lo2 . short_description = " outcome1 "
lo2 . workflow_state = 'active'
lo2 . data = { :rubric_criterion = > { :mastery_points = > 2 , :ratings = > [ { :description = > " e " , :points = > 50 } , { :description = > " me " , :points = > 2 } , { :description = > " Does Not Meet Expectations " , :points = > 0 . 5 } ] , :description = > " First outcome " , :points_possible = > 5 } }
lo2 . save!
default . add_item ( lo )
default . add_item ( lo2 )
2012-03-28 22:52:21 +08:00
# only select one of each type
@cm . copy_options = {
:discussion_topics = > { mig_id ( dt1 ) = > " 1 " , mig_id ( dt3 ) = > " 1 " } ,
:context_modules = > { mig_id ( cm ) = > " 1 " , mig_id ( cm2 ) = > " 0 " } ,
:attachments = > { mig_id ( att ) = > " 1 " , mig_id ( att2 ) = > " 0 " } ,
:wiki_pages = > { mig_id ( wiki ) = > " 1 " , mig_id ( wiki2 ) = > " 0 " } ,
2012-04-16 22:27:33 +08:00
:rubrics = > { mig_id ( rub1 ) = > " 1 " , mig_id ( rub2 ) = > " 0 " } ,
:learning_outcomes = > { mig_id ( lo ) = > " 1 " , mig_id ( lo2 ) = > " 0 " } ,
2012-03-28 22:52:21 +08:00
}
@cm . save!
run_course_copy
@copy_to . discussion_topics . find_by_migration_id ( mig_id ( dt1 ) ) . should_not be_nil
@copy_to . discussion_topics . find_by_migration_id ( mig_id ( dt2 ) ) . should be_nil
@copy_to . discussion_topics . find_by_migration_id ( mig_id ( dt3 ) ) . should_not be_nil
@copy_to . context_modules . find_by_migration_id ( mig_id ( cm ) ) . should_not be_nil
@copy_to . context_modules . find_by_migration_id ( mig_id ( cm2 ) ) . should be_nil
@copy_to . attachments . find_by_migration_id ( mig_id ( att ) ) . should_not be_nil
@copy_to . attachments . find_by_migration_id ( mig_id ( att2 ) ) . should be_nil
@copy_to . wiki . wiki_pages . find_by_migration_id ( mig_id ( wiki ) ) . should_not be_nil
@copy_to . wiki . wiki_pages . find_by_migration_id ( mig_id ( wiki2 ) ) . should be_nil
2012-04-16 22:27:33 +08:00
@copy_to . rubrics . find_by_migration_id ( mig_id ( rub1 ) ) . should_not be_nil
@copy_to . rubrics . find_by_migration_id ( mig_id ( rub2 ) ) . should be_nil
@copy_to . learning_outcomes . find_by_migration_id ( mig_id ( lo ) ) . should_not be_nil
@copy_to . learning_outcomes . find_by_migration_id ( mig_id ( lo2 ) ) . should be_nil
2012-03-28 22:52:21 +08:00
end
it " should copy learning outcomes into the new course " do
lo = @copy_from . learning_outcomes . new
lo . context = @copy_from
lo . short_description = " Lone outcome "
lo . description = " <p>Descriptions are boring</p> "
lo . workflow_state = 'active'
lo . data = { :rubric_criterion = > { :mastery_points = > 3 , :ratings = > [ { :description = > " Exceeds Expectations " , :points = > 5 } , { :description = > " Meets Expectations " , :points = > 3 } , { :description = > " Does Not Meet Expectations " , :points = > 0 } ] , :description = > " First outcome " , :points_possible = > 5 } }
lo . save!
old_root = LearningOutcomeGroup . default_for ( @copy_from )
old_root . add_item ( lo )
lo_g = @copy_from . learning_outcome_groups . new
lo_g . context = @copy_from
lo_g . title = " Lone outcome group "
lo_g . description = " <p>Groupage</p> "
lo_g . save!
old_root . add_item ( lo_g )
lo2 = @copy_from . learning_outcomes . new
lo2 . context = @copy_from
lo2 . short_description = " outcome in group "
lo2 . workflow_state = 'active'
lo2 . data = { :rubric_criterion = > { :mastery_points = > 2 , :ratings = > [ { :description = > " e " , :points = > 50 } , { :description = > " me " , :points = > 2 } , { :description = > " Does Not Meet Expectations " , :points = > 0 . 5 } ] , :description = > " First outcome " , :points_possible = > 5 } }
lo2 . save!
lo_g . add_item ( lo2 )
old_root . reload
# copy outcomes into new course
new_root = LearningOutcomeGroup . default_for ( @copy_to )
run_course_copy
@copy_to . learning_outcomes . count . should == @copy_from . learning_outcomes . count
@copy_to . learning_outcome_groups . count . should == @copy_from . learning_outcome_groups . count
new_root . sorted_content . count . should == old_root . sorted_content . count
lo_2 = new_root . sorted_content . first
lo_2 . short_description . should == lo . short_description
lo_2 . description . should == lo . description
lo_2 . data . should == lo . data
lo_g_2 = new_root . sorted_content . last
lo_g_2 . title . should == lo_g . title
lo_g_2 . description . should == lo_g . description
lo_g_2 . sorted_content . length . should == 1
lo_g_2 . root_learning_outcome_group_id . should == new_root . id
lo_g_2 . learning_outcome_group_id . should == new_root . id
lo_2 = lo_g_2 . sorted_content . first
lo_2 . short_description . should == lo2 . short_description
lo_2 . description . should == lo2 . description
lo_2 . data . should == lo2 . data
end
it " should copy a quiz when assignment is selected " do
pending unless Qti . qti_enabled?
@quiz = @copy_from . quizzes . create!
@quiz . did_edit
@quiz . offer!
@quiz . assignment . should_not be_nil
@cm . copy_options = {
:assignments = > { mig_id ( @quiz . assignment ) = > " 1 " } ,
:quizzes = > { mig_id ( @quiz ) = > " 0 " } ,
}
@cm . save!
run_course_copy
@copy_to . quizzes . find_by_migration_id ( mig_id ( @quiz ) ) . should_not be_nil
end
it " should copy a discussion topic when assignment is selected " do
topic = @copy_from . discussion_topics . build ( :title = > " topic " )
assignment = @copy_from . assignments . build ( :submission_types = > 'discussion_topic' , :title = > topic . title )
assignment . infer_due_at
assignment . saved_by = :discussion_topic
topic . assignment = assignment
topic . save
@cm . copy_options = {
:assignments = > { mig_id ( assignment ) = > " 1 " } ,
:discussion_topics = > { mig_id ( topic ) = > " 0 " } ,
}
@cm . save!
run_course_copy
@copy_to . discussion_topics . find_by_migration_id ( mig_id ( topic ) ) . should_not be_nil
end
it " should assign the correct parent folder when the parent folder has already been created " do
folder = Folder . root_folders ( @copy_from ) . first
folder = folder . sub_folders . create! ( :context = > @copy_from , :name = > 'folder_1' )
att = Attachment . create! ( :filename = > 'dummy.txt' , :uploaded_data = > StringIO . new ( 'fakety' ) , :folder = > folder , :context = > @copy_from )
folder = folder . sub_folders . create! ( :context = > @copy_from , :name = > 'folder_2' )
folder = folder . sub_folders . create! ( :context = > @copy_from , :name = > 'folder_3' )
old_attachment = Attachment . create! ( :filename = > 'merge.test' , :uploaded_data = > StringIO . new ( 'ohey' ) , :folder = > folder , :context = > @copy_from )
run_course_copy
new_attachment = @copy_to . attachments . find_by_migration_id ( mig_id ( old_attachment ) )
new_attachment . should_not be_nil
new_attachment . full_path . should == " course files/folder_1/folder_2/folder_3/merge.test "
folder . reload
end
it " should perform day substitutions " do
@copy_from . assert_assignment_group
today = Time . now . utc
asmnt = @copy_from . assignments . build
asmnt . due_at = today
asmnt . workflow_state = 'published'
asmnt . save!
@copy_from . reload
@cm . migration_settings [ :migration_ids_to_import ] = {
:copy = > {
:shift_dates = > true ,
:day_substitutions = > { today . wday . to_s = > ( today . wday + 1 ) . to_s }
}
}
@cm . save!
run_course_copy
new_assignment = @copy_to . assignments . first
# new_assignment.due_at.should == today + 1.day does not work
new_assignment . due_at . to_i . should_not == asmnt . due_at . to_i
( new_assignment . due_at . to_i - ( today + 1 . day ) . to_i ) . abs . should < 60
end
end
2012-04-03 06:38:05 +08:00
context " import_object? " do
before do
@cm = ContentMigration . new
end
it " should return true for everything if there are no copy options " do
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == true
end
it " should return true for everything if 'everything' is selected " do
@cm . migration_ids_to_import = { :copy = > { :everything = > " 1 " } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == true
end
it " should return true if there are no copy options " do
@cm . migration_ids_to_import = { :copy = > { } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == true
end
it " should return false for nil objects " do
@cm . import_object? ( " content_migrations " , nil ) . should == false
end
it " should return true for all object types if the all_ option is true " do
@cm . migration_ids_to_import = { :copy = > { :all_content_migrations = > " 1 " } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == true
end
it " should return false for objects not selected " do
@cm . save!
@cm . migration_ids_to_import = { :copy = > { :all_content_migrations = > " 0 " } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == false
@cm . migration_ids_to_import = { :copy = > { :content_migrations = > { } } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == false
@cm . migration_ids_to_import = { :copy = > { :content_migrations = > { CC :: CCHelper . create_key ( @cm ) = > " 0 " } } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == false
end
it " should return true for selected objects " do
@cm . save!
@cm . migration_ids_to_import = { :copy = > { :content_migrations = > { CC :: CCHelper . create_key ( @cm ) = > " 1 " } } }
@cm . import_object? ( " content_migrations " , CC :: CCHelper . create_key ( @cm ) ) . should == true
end
end
2012-04-16 22:27:33 +08:00
end