Website : rimsha.abasa.com
backdoor
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
canvas
/
spec
/
lib
/
Filename :
must_view_module_progressor_spec.rb
back
Copy
# frozen_string_literal: true # # Copyright (C) 2016 - present 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/>. # describe "MustViewModuleProgressor" do def create_item(item_type) case item_type when :page @course.wiki_pages.create!(title: "some page") when :assignment @course.assignments.create!(title: "some assignment") when :discussion @course.discussion_topics.create!(title: "some discussion") when :attachment @course.attachments.create!(uploaded_data: stub_png_data("my-pic.png")) else raise "unrecognized item type: #{item_type}" end end def item_type_of(item) case item when WikiPage then "page" when Assignment then "assignment" when DiscussionTopic then "discussion" when Attachment then "attachment" else raise "unknown item type: #{item.class}" end end def add_module_item(mod, item, requirement_type = "must_view") item_tag = mod.add_item(id: item.id, type: item_type_of(item)) mod.completion_requirements = mod.completion_requirements + [{ id: item_tag.id, type: requirement_type.to_s }] mod.save! item_tag end def module_with_item_return_all(item_type, requirement_type = "must_view") mod = @course.context_modules.create!(name: "some module") item = create_item(item_type) item_tag = add_module_item(mod, item, requirement_type) [mod, item, item_tag] end def module_with_item(item_type, requirement_type = "must_view") module_with_item_return_all(item_type, requirement_type).first end def sequential_module_progression_fixture(assignment_requirement_type: "must_view") mod = @course.context_modules.create!(name: "some module") initial_page = @course.wiki_pages.create!(title: "initial page") initial_page_tag = mod.add_item(id: initial_page.id, type: "page") assignment = @course.assignments.create!(title: "some assignment") assignment_tag = mod.add_item(id: assignment.id, type: "assignment") final_page = @course.wiki_pages.create!(title: "some page") final_page_tag = mod.add_item(id: final_page.id, type: "page") mod.completion_requirements = { initial_page_tag.id => { type: "must_view" }, assignment_tag.id => { type: assignment_requirement_type }, final_page_tag.id => { type: "must_view" }, } mod.require_sequential_progress = true mod.save! { mod:, initial_page: { item: initial_page, tag: initial_page_tag }, assignment: { item: assignment, tag: assignment_tag }, final_page: { item: final_page, tag: final_page_tag }, } end describe "#make_progress" do before(:once) do course_with_student(active_all: true) end # needed to get updated info as progress is made it "calls evaluate_for on modules" do @course.context_modules.create!(name: "some module") expect_any_instance_of(ContextModule).to receive(:evaluate_for) progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress end it "marks several must_view requirements in random access module as viewed" do mod, _, first_page_tag = module_with_item_return_all(:page) add_module_item(mod, create_item(:assignment), "must_submit") second_page_tag = add_module_item(mod, create_item(:page)) progression = mod.find_or_create_progression(@student) expect(progression.requirements_met).to be_empty progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression.reload actual = progression.requirements_met.sort_by { |req| req[:id] } expected = [ { id: first_page_tag.id, type: "must_view" }, { id: second_page_tag.id, type: "must_view" }, ].sort_by { |ex| ex[:id] } expect(actual).to eq(expected) end it "follows module prerequisites" do mods = [ module_with_item(:page), module_with_item(:page), ] mods[1].prerequisites = [{ id: mods[0].id, name: mods[0].name, type: "context_module" }] mods[1].save! progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress @course.context_modules.each do |mod| progression = mod.find_or_create_progression(@student) tag = mod.content_tags.first expect(progression.requirements_met).to eq([{ id: tag.id, type: "must_view" }]) end end it "is blocked by prerequisites" do mods = (1..2).map do |i| @course.context_modules.create!(name: "module #{i}") end add_module_item(mods[0], create_item(:assignment), "must_submit") add_module_item(mods[1], create_item(:page)) mods[1].prerequisites = [{ id: mods[0].id, name: mods[0].name, type: "context_module" }] mods[1].save! progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mods[1].reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([]) end it "is blocked by sequential progress" do sequence = sequential_module_progression_fixture( assignment_requirement_type: "must_contribute" ) mod = sequence[:mod] progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([ { id: sequence[:initial_page][:tag].id, type: "must_view" } ]) end it "can follow sequential progress" do sequence = sequential_module_progression_fixture mod = sequence[:mod] progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met.size).to eq(3) end it "can follow sequential progress through already completed non-must-view items" do sequence = sequential_module_progression_fixture( assignment_requirement_type: "must_contribute" ) mod = sequence[:mod] mod.update_for(@student, :contributed, sequence[:assignment][:tag]) progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met.size).to eq(3) end it "does not mark locked assignment as complete" do mod, assignment = module_with_item_return_all(:assignment) assignment.lock_at = Time.now.utc - 2.days assignment.save! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([]) end it "does not mark locked discussion as complete" do mod, discussion = module_with_item_return_all(:discussion) discussion.lock_at = Time.now.utc - 2.days discussion.save! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([]) end it "does not mark locked file as complete" do mod, att = module_with_item_return_all(:attachment) att.lock_at = Time.now.utc - 2.days att.save! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([]) end # testing assignments should cover other unpublished things too it "does not mark unpublished assignments as complete" do mod, assignment = module_with_item_return_all(:assignment) assignment.unpublish! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq([]) end it "proceeds through unpublished assignments for sequential modules" do sequence = sequential_module_progression_fixture( assignment_requirement_type: "must_contribute" ) mod = sequence[:mod] sequence[:assignment][:item].unpublish! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) reqs = progression.requirements_met.sort_by { |req| req[:id] } expected = [ { id: sequence[:initial_page][:tag].id, type: "must_view" }, { id: sequence[:final_page][:tag].id, type: "must_view" }, ].sort_by { |ex| ex[:id] } expect(reqs).to eq expected end # items can be unpublished separately from their content it "proceeds through modules with unpublished content tags" do sequence = sequential_module_progression_fixture( assignment_requirement_type: "must_contribute" ) mod = sequence[:mod] sequence[:assignment][:tag].unpublish! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met.size).to eq 2 end it "proceeds through modules with unpublished assignments" do first_mod, assignment = module_with_item_return_all(:assignment, "must_contribute") first_page = create_item(:page) first_page_tag = add_module_item(first_mod, first_page) second_mod, _, second_page_tag = module_with_item_return_all(:page) second_mod.prerequisites = [{ id: first_mod.id, name: first_mod.name, type: "context_module" }] second_mod.save! assignment.unpublish! @course.reload progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress first_progression = first_mod.find_or_create_progression(@student) expect(first_progression.requirements_met).to eq([{ id: first_page_tag.id, type: "must_view" }]) second_progression = second_mod.find_or_create_progression(@student) expect(second_progression.requirements_met).to eq([{ id: second_page_tag.id, type: "must_view" }]) end it "triggers completion events" do expect_any_instance_of(ContextModuleProgression).to receive(:trigger_completion_events) module_with_item(:page) progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress end it "ignores assignments that are hidden by overrides" do first_student = @student course_with_student(course: @course, active_all: true) second_student = @student sequence = sequential_module_progression_fixture( assignment_requirement_type: "must_contribute" ) mod = sequence[:mod] assignment = sequence[:assignment][:item] create_adhoc_override_for_assignment(assignment, second_student) assignment.reload assignment.only_visible_to_overrides = true assignment.save! expect(assignment.visible_to_user?(first_student)).to be_falsy expect(assignment.visible_to_user?(second_student)).to be_truthy progressor = MustViewModuleProgressor.new(first_student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(first_student) expect(progression.requirements_met.size).to eq 2 progressor = MustViewModuleProgressor.new(second_student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(second_student) expect(progression.requirements_met.size).to eq 1 end it "does not progress items in unpublished modules" do mod = module_with_item(:page) mod.unpublish! progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = mod.reload.find_or_create_progression(@student) expect(progression.requirements_met.size).to eq 0 end it "does not progress items in locked modules" do first_mod = module_with_item(:page) second_mod = module_with_item(:page) second_mod.prerequisites = [{ id: first_mod.id, name: first_mod.name, type: "context_module" }] second_mod.save! first_mod.unlock_at = Time.now.utc + 2.days first_mod.save! progressor = MustViewModuleProgressor.new(@student, @course) progressor.make_progress progression = first_mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq [] progression = second_mod.reload.find_or_create_progression(@student) expect(progression.requirements_met).to eq [] end end describe "#current_progress" do before :once do course_with_student(active_all: true) @module, @assignment = module_with_item_return_all(:assignment, "must_contribute") end it "exports module status into a hash" do progress = MustViewModuleProgressor.new(@student, @course).current_progress expect(progress[@module.id][:status]).to eq "unlocked" expect(progress[@module.id][:items].keys.length).to eq 1 end it "exports module item completion into a hash" do assign_item = @module.content_tags.find_by(content: @assignment) progress = MustViewModuleProgressor.new(@student, @course).current_progress expect(progress[@module.id][:items][assign_item.id]).to be false end it "does not create progressions for non-enrolled admins and allow view if appropriate" do account_admin_user progress = MustViewModuleProgressor.new(@admin, @course).current_progress expect(progress[@module.id][:status]).to eq "unlocked" expect(ContextModuleProgression.where(user: @admin, context_module: @module).count).to eq 0 end it "does not create progressions for non-enrolled non-admins" do course_factory(is_public: true, active_all: true) user_factory(active_all: true) modul = module_with_item(:assignment, "must_contribute") progress = MustViewModuleProgressor.new(@user, @course).current_progress expect(progress[modul.id][:status]).to eq "unlocked" expect(ContextModuleProgression.where(user: @user, context_module: modul).count).to eq 0 end end end