Great Expectations, fixes SD-2065
Find/fix/prevent weird stuff we are doing (or not doing) with `expect`. Chapter I: "I have been bent and broken, but - I hope - into a better shape." Disallow `expect`s in a `before`. `before` is by definition before the test, so it's not the place to be asserting anything. You can of course still set up mocks there. Chapter II: "Take nothing on its looks; take everything on evidence. There's no better rule." Ensure every `expect` actually runs. i.e. it needs `to` or `not_to` in order to actually do anything. Chapter III: "Ask no questions, and you'll be told no lies." In selenium land, ensure every spec has at least one expecation. In regular rspec land we just warn to stderr, but we may get more strict in the future. Test Plan: Specs Change-Id: I5fc353ee8171e5191853d45f42ae42478f9220b4 Reviewed-on: https://gerrit.instructure.com/101224 Tested-by: Jenkins Reviewed-by: Rob Orton <rob@instructure.com> Reviewed-by: Landon Wilkins <lwilkins@instructure.com> Product-Review: Jon Jensen <jon@instructure.com> QA-Review: Jon Jensen <jon@instructure.com>
This commit is contained in:
parent
09d187e470
commit
fb3966a62d
|
@ -258,8 +258,6 @@ Implemented for: Canvas LMS}
|
|||
'', ['itemType', 'course'],
|
||||
['itemID', @course.to_param],
|
||||
['clearState', ''])
|
||||
expect(status).to eq "Success"
|
||||
|
||||
@mock_migration = ContentMigration.create!(context: @course)
|
||||
def @mock_migration.export_content
|
||||
self.workflow_state = 'importing'
|
||||
|
@ -271,8 +269,6 @@ Implemented for: Canvas LMS}
|
|||
'PublishServerItem', 'nobody@example.com', 'asdfasdf', context,
|
||||
['itemType', 'quiz'], ['itemName', 'my quiz'], ['uploadType', 'zipPackage'],
|
||||
['fileName', 'import.zip'], ['fileData', 'pretend this is a zip file'])
|
||||
expect(status).to eq "Success"
|
||||
expect(item_id).to eq 'pending'
|
||||
@token = context
|
||||
end
|
||||
|
||||
|
|
|
@ -52,23 +52,6 @@ def api_call(method, path, params, body_params = {}, headers = {}, opts = {})
|
|||
raw_api_call(method, path, params, body_params, headers, opts)
|
||||
if opts[:expected_status]
|
||||
assert_status(opts[:expected_status])
|
||||
else
|
||||
unless response.success?
|
||||
error_message = response.body
|
||||
begin
|
||||
json = JSON.parse(response.body)
|
||||
error_report_id = json['error_report_id']
|
||||
error_report = ErrorReport.find_by(id: error_report_id) if error_report_id
|
||||
if error_report
|
||||
error_message << "\n"
|
||||
error_message << error_report.message
|
||||
error_message << "\n"
|
||||
error_message << error_report.backtrace
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
end
|
||||
end
|
||||
expect(response).to be_success, error_message
|
||||
end
|
||||
|
||||
if response.headers['Link']
|
||||
|
@ -76,14 +59,9 @@ def api_call(method, path, params, body_params = {}, headers = {}, opts = {})
|
|||
Api.parse_pagination_links(response.headers['Link'])
|
||||
end
|
||||
|
||||
if jsonapi_call?(headers) && method == :delete
|
||||
assert_status(204)
|
||||
return
|
||||
end
|
||||
|
||||
case params[:format]
|
||||
when 'json'
|
||||
expect(response.header[content_type_key]).to eq 'application/json; charset=utf-8'
|
||||
raise "got non-json" unless response.header[content_type_key] == 'application/json; charset=utf-8'
|
||||
|
||||
body = response.body
|
||||
if body.respond_to?(:call)
|
||||
|
@ -133,7 +111,7 @@ def raw_api_call(method, path, params, body_params = {}, headers = {}, opts = {}
|
|||
enable_forgery_protection do
|
||||
route_params = params_from_with_nesting(method, path)
|
||||
route_params.each do |key, value|
|
||||
expect(params[key].to_s).to eq(value.to_s), lambda{ "Expected value of params[\'#{key}\'] to equal #{value}, actual: #{params[key]}"}
|
||||
raise "Expected value of params[\'#{key}\'] to equal #{value}, actual: #{params[key]}" unless params[key].to_s == value.to_s
|
||||
end
|
||||
if @use_basic_auth
|
||||
user_session(@user)
|
||||
|
|
|
@ -588,7 +588,6 @@ describe "API Authentication", type: :request do
|
|||
user_with_pseudonym(:active_user => true, :username => 'test1@example.com', :password => 'test1234')
|
||||
course_with_teacher(:user => @user)
|
||||
@token = @user.access_tokens.create!
|
||||
expect(@token.full_token).not_to be_nil
|
||||
end
|
||||
|
||||
def check_used
|
||||
|
|
|
@ -1477,7 +1477,7 @@ describe AssignmentsApiController, type: :request do
|
|||
api_call_to_update_adhoc_override(student_ids: [@student.id])
|
||||
|
||||
ao = @assignment.assignment_overrides.where(set_type: 'ADHOC').first
|
||||
expect(AssignmentOverrideStudent.count ==1)
|
||||
expect(AssignmentOverrideStudent.count).to eq 1
|
||||
end
|
||||
|
||||
it 'allows the update of an adhoc override with different student' do
|
||||
|
@ -3246,7 +3246,6 @@ describe AssignmentsApiController, type: :request do
|
|||
@tool_tag.save!
|
||||
@assignment.submission_types = 'external_tool'
|
||||
@assignment.save!
|
||||
expect(@assignment.external_tool_tag).not_to be_nil
|
||||
end
|
||||
|
||||
before :each do
|
||||
|
|
|
@ -321,7 +321,6 @@ describe "Modules API", type: :request do
|
|||
:course_id => @course.to_param }
|
||||
@test_modules = (1..4).map { |x| @course.context_modules.create! :name => "test module #{x}" }
|
||||
@test_modules[2..3].each { |m| m.update_attribute(:workflow_state , 'unpublished') }
|
||||
expect(@test_modules.map { |tm| tm.workflow_state }).to eq %w(active active unpublished unpublished)
|
||||
@modules_to_update = [@test_modules[1], @test_modules[3]]
|
||||
|
||||
@wiki_page = @course.wiki.wiki_pages.create(:title => 'Wiki Page Title')
|
||||
|
|
|
@ -1763,9 +1763,10 @@ describe DiscussionTopicsController, type: :request do
|
|||
RoleOverride.create!(:context => @course.account, :permission => 'read_forum',
|
||||
:role => observer_role, :enabled => false)
|
||||
|
||||
expect { api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics.json",
|
||||
{:controller => 'discussion_topics', :action => 'index', :format => 'json',
|
||||
:course_id => @course.id.to_s}) }.to raise_error
|
||||
api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics.json",
|
||||
{:controller => 'discussion_topics', :action => 'index', :format => 'json',
|
||||
:course_id => @course.id.to_s})
|
||||
expect(response).to be_client_error
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2492,7 +2493,6 @@ describe DiscussionTopicsController, type: :request do
|
|||
|
||||
before :each do
|
||||
course_with_teacher(active_all: true, is_public: true) # sets @teacher and @course
|
||||
expect(@course.is_public).to be_truthy
|
||||
account_admin_user(account: @course.account) # sets @admin
|
||||
@student1 = student_in_course(active_all: true).user
|
||||
@student2 = student_in_course(active_all: true).user
|
||||
|
|
|
@ -212,7 +212,7 @@ describe "Favorites API", type: :request do
|
|||
expect(@user.favorites.size).to eql(0)
|
||||
json = api_call(:get, "/api/v1/users/self/favorites/groups",
|
||||
:controller=>"favorites", :action=>"list_favorite_groups", :format=>"json")
|
||||
expect(json.any?)
|
||||
expect(json.any?).to be
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -66,8 +66,7 @@ describe 'Moderated Grades API', type: :request do
|
|||
@parsed_json = api_call :post,
|
||||
"/api/v1/courses/#{@course.id}/assignments/#{@assignment.id}/moderated_students",
|
||||
{controller: 'moderation_set', action: 'create',
|
||||
format: 'json', course_id: @course.id, assignment_id: @assignment.id}, {}, {},
|
||||
{ expected_status: 400 }
|
||||
format: 'json', course_id: @course.id, assignment_id: @assignment.id}, {}, {}
|
||||
end
|
||||
|
||||
it 'responds with a bad request' do
|
||||
|
|
|
@ -663,23 +663,12 @@ describe "Outcomes API", type: :request do
|
|||
context "mastery calculations" do
|
||||
context "not allow updating the outcome after being used for assessing" do
|
||||
before :each do
|
||||
expect(@outcome).not_to be_assessed
|
||||
|
||||
@outcome.calculation_method = 'decaying_average'
|
||||
@outcome.calculation_int = 62
|
||||
@outcome.save!
|
||||
@outcome.reload
|
||||
|
||||
expect(@outcome.calculation_method).to eq('decaying_average')
|
||||
expect(@outcome.calculation_int).to eq(62)
|
||||
|
||||
assess_outcome(@outcome)
|
||||
expect(@outcome).to be_assessed
|
||||
|
||||
# make sure that the process of getting assessed didn't change
|
||||
# the things our tests expect to be true
|
||||
expect(@outcome.calculation_method).to eq('decaying_average')
|
||||
expect(@outcome.calculation_int).to eq(62)
|
||||
end
|
||||
|
||||
let(:update_outcome_api) do
|
||||
|
|
|
@ -183,10 +183,6 @@ describe 'Provisional Grades API', type: :request do
|
|||
@submission = @assignment.submit_homework(@student, :body => "hello")
|
||||
@submission.add_comment(author: @ta, provisional: true, comment: 'A provisional comment')
|
||||
@provisional_grade = @submission.provisional_grades.first
|
||||
|
||||
expect(@submission.workflow_state).to eq('submitted')
|
||||
expect(@submission.grade).to be_nil
|
||||
expect(@provisional_grade.graded_at).to be_nil
|
||||
end
|
||||
|
||||
it 'publishes an empty provisional grade for an active student' do
|
||||
|
|
|
@ -184,14 +184,11 @@ describe Quizzes::QuizQuestionsController, type: :request do
|
|||
end
|
||||
|
||||
context "non-existent question" do
|
||||
before do
|
||||
@json = api_call(:get, "/api/v1/courses/#{@course.id}/quizzes/#{@quiz.id}/questions/9034831",
|
||||
{:controller => "quizzes/quiz_questions", :action => "show", :format => "json", :course_id => @course.id.to_s, :quiz_id => @quiz.id.to_s, :id => "9034831"},
|
||||
{}, {}, {:expected_status => 404})
|
||||
end
|
||||
|
||||
it "should return a not found error message" do
|
||||
expect(@json.inspect).to include "does not exist"
|
||||
json = api_call(:get, "/api/v1/courses/#{@course.id}/quizzes/#{@quiz.id}/questions/9034831",
|
||||
{:controller => "quizzes/quiz_questions", :action => "show", :format => "json", :course_id => @course.id.to_s, :quiz_id => @quiz.id.to_s, :id => "9034831"},
|
||||
{}, {}, {:expected_status => 404})
|
||||
expect(json.inspect).to include "does not exist"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -241,14 +241,11 @@ describe Quizzes::QuizzesApiController, type: :request do
|
|||
end
|
||||
|
||||
context "non-existent quiz" do
|
||||
before do
|
||||
@json = api_call(:get, "/api/v1/courses/#{@course.id}/quizzes/10101",
|
||||
{:controller=>"quizzes/quizzes_api", :action=>"show", :format=>"json", :course_id=>"#{@course.id}", :id => "10101"},
|
||||
{}, {}, {:expected_status => 404})
|
||||
end
|
||||
|
||||
it "should return a not found error message" do
|
||||
expect(@json.inspect).to include "does not exist"
|
||||
json = api_call(:get, "/api/v1/courses/#{@course.id}/quizzes/10101",
|
||||
{:controller=>"quizzes/quizzes_api", :action=>"show", :format=>"json", :course_id=>"#{@course.id}", :id => "10101"},
|
||||
{}, {}, {:expected_status => 404})
|
||||
expect(json.inspect).to include "does not exist"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -315,7 +315,7 @@ describe UserObserveesController, type: :request do
|
|||
unique_id: student_pseudonym.unique_id,
|
||||
password: student_pseudonym.password,
|
||||
}
|
||||
expect(create_call({observee: observee}, api_user: student, expected_status: 401))
|
||||
create_call({observee: observee}, api_user: student, expected_status: 401)
|
||||
|
||||
expect(student.reload.observed_users).to eq []
|
||||
end
|
||||
|
|
|
@ -33,8 +33,6 @@ describe AssignmentsController do
|
|||
:assignment_group => @group,
|
||||
:due_at => Time.zone.now + 1.week
|
||||
)
|
||||
expect(@assignment.assignment_group).to eql(@group)
|
||||
expect(@group.assignments).to be_include(@assignment)
|
||||
@assignment
|
||||
end
|
||||
|
||||
|
|
|
@ -1473,7 +1473,6 @@ describe CoursesController do
|
|||
Assignment.where(:id => @assignment).update_all(:updated_at => @time)
|
||||
|
||||
@assignment.reload
|
||||
expect(@assignment.updated_at).to eq @time
|
||||
end
|
||||
|
||||
it "should touch content when is_public is updated" do
|
||||
|
|
|
@ -389,10 +389,6 @@ describe Login::SamlController do
|
|||
)
|
||||
controller.request.env['canvas.domain_root_account'] = @account
|
||||
post :create, :SAMLResponse => "foo", :RelayState => "/courses"
|
||||
|
||||
expect(response).to redirect_to(courses_url)
|
||||
expect(session[:saml_unique_id]).to eq @unique_id
|
||||
expect(session[:login_aac]).to eq @aac2.id
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
|
|
|
@ -452,10 +452,6 @@ describe ApplicationHelper do
|
|||
end
|
||||
|
||||
describe "hidden dialogs" do
|
||||
before do
|
||||
expect(hidden_dialogs).to be_empty
|
||||
end
|
||||
|
||||
it "should generate empty string when there are no dialogs" do
|
||||
str = render_hidden_dialogs
|
||||
expect(str).to eq ''
|
||||
|
|
|
@ -277,14 +277,14 @@ describe GradebooksHelper do
|
|||
|
||||
describe '#percentage?' do
|
||||
it 'returns true if given grade is a percentage' do
|
||||
expect(helper.percentage?('42%'))
|
||||
expect(helper.percentage?('42.32%'))
|
||||
expect(helper.percentage?('42%')).to eq true
|
||||
expect(helper.percentage?('42.32%')).to eq true
|
||||
end
|
||||
|
||||
it 'returns false if given grade is not a percentage' do
|
||||
expect(helper.percentage?('42'))
|
||||
expect(helper.percentage?('42.32'))
|
||||
expect(helper.percentage?('A'))
|
||||
expect(helper.percentage?('42')).to eq false
|
||||
expect(helper.percentage?('42.32')).to eq false
|
||||
expect(helper.percentage?('A')).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -41,14 +41,12 @@ describe "concluded/unconcluded courses" do
|
|||
@group = @course.assignment_groups.create!(:name => "default")
|
||||
@assignment = @course.assignments.create!(:submission_types => 'online_quiz', :title => 'quiz assignment', :assignment_group => @group)
|
||||
@quiz = @assignment.reload.quiz
|
||||
expect(@quiz).not_to be_nil
|
||||
@qsub = Quizzes::SubmissionManager.new(@quiz).find_or_create_submission(@student)
|
||||
@qsub.quiz_data = [{:correct_comments=>"", :assessment_question_id=>nil, :incorrect_comments=>"", :question_name=>"Question 1", :points_possible=>1, :question_text=>"Which book(s) are required for this course?", :name=>"Question 1", :id=>128, :answers=>[{:weight=>0, :text=>"A", :comments=>"", :id=>1490}, {:weight=>0, :text=>"B", :comments=>"", :id=>1020}, {:weight=>0, :text=>"C", :comments=>"", :id=>7051}], :question_type=>"multiple_choice_question"}]
|
||||
@qsub.submission_data = [{:points=>0, :text=>"7051", :question_id=>128, :correct=>false, :answer_id=>7051}]
|
||||
@qsub.workflow_state = 'complete'
|
||||
@qsub.save!
|
||||
@sub = @qsub.submission
|
||||
expect(@sub).not_to be_nil
|
||||
end
|
||||
|
||||
it "should let the teacher change grades in the speed grader by default" do
|
||||
|
|
|
@ -42,12 +42,13 @@ describe "discussion_topics" do
|
|||
end
|
||||
|
||||
it "should not allow concluded students to update topic" do
|
||||
student_enrollment = course_with_student(:course => @course, :user => @user, :active_enrollment => true)
|
||||
student_enrollment = course_with_student(:course => @course, :active_all => true)
|
||||
@topic = DiscussionTopic.new(:context => @course, :title => "will this work?", :user => @user)
|
||||
@topic.save!
|
||||
expect(@topic.grants_right?(@user, :update))
|
||||
expect(@topic.grants_right?(@user, :update)).to be
|
||||
student_enrollment.send("conclude")
|
||||
expect(!@topic.grants_right?(@user, :update))
|
||||
AdheresToPolicy::Cache.clear
|
||||
expect(@topic.grants_right?(@user, :update)).not_to be
|
||||
end
|
||||
|
||||
it "should allow teachers to edit concluded students topics" do
|
||||
|
@ -55,9 +56,10 @@ describe "discussion_topics" do
|
|||
student_enrollment = course_with_student(:course => @course, :user => @student, :active_enrollment => true)
|
||||
@topic = DiscussionTopic.new(:context => @course, :title => "will this work?", :user => @student)
|
||||
@topic.save!
|
||||
expect(@topic.grants_right?(@teacher, :update))
|
||||
expect(@topic.grants_right?(@teacher, :update)).to be
|
||||
student_enrollment.send("conclude")
|
||||
expect(@topic.grants_right?(@teacher, :update))
|
||||
AdheresToPolicy::Cache.clear
|
||||
expect(@topic.grants_right?(@teacher, :update)).to be
|
||||
end
|
||||
|
||||
it "should show speed grader button" do
|
||||
|
|
|
@ -31,6 +31,9 @@ describe "one time passwords" do
|
|||
context "mid-login" do
|
||||
before do
|
||||
post '/login/canvas', :pseudonym_session => { :unique_id => @pseudonym.unique_id, :password => 'qwertyuiop' }
|
||||
end
|
||||
|
||||
it "should redirect" do
|
||||
expect(response).to redirect_to(otp_login_url)
|
||||
end
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ describe "QuizRegrading" do
|
|||
course_with_student_logged_in(active_all: true)
|
||||
quiz_model(course: @course)
|
||||
@regrade = @quiz.quiz_regrades.where(quiz_id: @quiz.id, quiz_version: @quiz.version_number).first_or_create(user: @student)
|
||||
expect(@regrade).not_to be_new_record
|
||||
@true_false_question = create_quiz_question!({
|
||||
:points_possible => 1,
|
||||
:question_type => 'true_false_question',
|
||||
|
@ -73,7 +72,6 @@ describe "QuizRegrading" do
|
|||
@submission = @quiz.generate_submission(@student)
|
||||
reset_submission_data!
|
||||
@submission.save!
|
||||
expect(@submission.score).to eq 0.5
|
||||
end
|
||||
|
||||
it 'succesfully regrades the submissions and updates the scores' do
|
||||
|
|
|
@ -160,10 +160,7 @@ describe GradeCalculator do
|
|||
describe "group with no grade or muted grade" do
|
||||
before(:each) do
|
||||
two_groups_two_assignments(50, 10, 50, 10)
|
||||
expect(@user.enrollments.first.computed_current_score).to eql(nil)
|
||||
expect(@user.enrollments.first.computed_final_score).to eql(0.0)
|
||||
@submission = @assignment.grade_student(@user, grade: "5", grader: @teacher)
|
||||
expect(@submission[0].score).to eql(5.0)
|
||||
end
|
||||
|
||||
it "should ignore no grade for current grade calculation, even when weighted" do
|
||||
|
|
|
@ -27,9 +27,7 @@ describe Turnitin::Client do
|
|||
end
|
||||
|
||||
def turnitin_submission
|
||||
expects_job_with_tag('Submission#submit_to_turnitin') do
|
||||
@submission = @assignment.submit_homework(@user, :submission_type => 'online_upload', :attachments => [attachment_model(:context => @user, :content_type => 'text/plain')])
|
||||
end
|
||||
@submission = @assignment.submit_homework(@user, :submission_type => 'online_upload', :attachments => [attachment_model(:context => @user, :content_type => 'text/plain')])
|
||||
@submission.reload
|
||||
end
|
||||
|
||||
|
|
|
@ -989,7 +989,6 @@ describe Account do
|
|||
|
||||
before do
|
||||
account.authentication_providers.scope.delete_all
|
||||
expect(account.delegated_authentication?).to eq false
|
||||
end
|
||||
|
||||
it "is false for LDAP" do
|
||||
|
|
|
@ -577,8 +577,6 @@ describe ActiveRecord::Base do
|
|||
@u4 = User.create!(name: 'b')
|
||||
|
||||
@us = [@u1, @u2, @u3, @u4]
|
||||
# for sanity
|
||||
expect(User.where(id: @us, name: nil).order(:id).all).to eq [@u1, @u3]
|
||||
end
|
||||
|
||||
it "should sort nulls first" do
|
||||
|
|
|
@ -179,7 +179,7 @@ describe Assignment do
|
|||
end
|
||||
|
||||
it 'returns a jwt' do
|
||||
expect(Canvas::Security.decode_jwt @assignment.secure_params)
|
||||
expect(Canvas::Security.decode_jwt(@assignment.secure_params)).to be
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -4036,87 +4036,80 @@ describe Assignment do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def setup_assignment_with_group
|
||||
assignment_model(:group_category => "Study Groups", :course => @course)
|
||||
@group = @a.context.groups.create!(:name => "Study Group 1", :group_category => @a.group_category)
|
||||
@u1 = @a.context.enroll_user(User.create(:name => "user 1")).user
|
||||
@u2 = @a.context.enroll_user(User.create(:name => "user 2")).user
|
||||
@u3 = @a.context.enroll_user(User.create(:name => "user 3")).user
|
||||
@group.add_user(@u1)
|
||||
@group.add_user(@u2)
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
def setup_assignment_without_submission
|
||||
assignment_model(:course => @course)
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
def setup_assignment_with_homework
|
||||
setup_assignment_without_submission
|
||||
res = @assignment.submit_homework(@user, {:submission_type => 'online_text_entry', :body => 'blah'})
|
||||
expect(res).not_to be_nil
|
||||
expect(res).to be_is_a(Submission)
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
def setup_assignment_with_students
|
||||
@graded_notify = Notification.create!(:name => "Submission Graded")
|
||||
@grade_change_notify = Notification.create!(:name => "Submission Grade Changed")
|
||||
@stu1 = @student
|
||||
@course.enroll_student(@stu2 = user_factory)
|
||||
@assignment = @course.assignments.create(:title => "asdf", :points_possible => 10)
|
||||
@sub1 = @assignment.grade_student(@stu1, grade: 9, grader: @teacher).first
|
||||
expect(@sub1.score).to eq 9
|
||||
# Took this out until it is asked for
|
||||
# @sub1.published_score.should_not == @sub1.score
|
||||
expect(@sub1.published_score).to eq @sub1.score
|
||||
@assignment.reload
|
||||
expect(@assignment.submissions).to be_include(@sub1)
|
||||
end
|
||||
|
||||
def submit_homework(student)
|
||||
file_context = @assignment.group_category.group_for(student) if @assignment.has_group_category?
|
||||
file_context ||= student
|
||||
a = Attachment.create! context: file_context,
|
||||
filename: "homework.pdf",
|
||||
uploaded_data: StringIO.new("blah blah blah")
|
||||
@assignment.submit_homework(student, attachments: [a],
|
||||
submission_type: "online_upload")
|
||||
a
|
||||
end
|
||||
|
||||
def zip_submissions
|
||||
zip = Attachment.new filename: 'submissions.zip'
|
||||
zip.user = @teacher
|
||||
zip.workflow_state = 'to_be_zipped'
|
||||
zip.context = @assignment
|
||||
zip.save!
|
||||
ContentZipper.process_attachment(zip, @teacher)
|
||||
raise "zip failed" if zip.workflow_state != "zipped"
|
||||
zip
|
||||
end
|
||||
|
||||
def setup_differentiated_assignments(opts={})
|
||||
if !opts[:course]
|
||||
course_with_teacher(active_all: true)
|
||||
def setup_assignment_with_group
|
||||
assignment_model(:group_category => "Study Groups", :course => @course)
|
||||
@group = @a.context.groups.create!(:name => "Study Group 1", :group_category => @a.group_category)
|
||||
@u1 = @a.context.enroll_user(User.create(:name => "user 1")).user
|
||||
@u2 = @a.context.enroll_user(User.create(:name => "user 2")).user
|
||||
@u3 = @a.context.enroll_user(User.create(:name => "user 3")).user
|
||||
@group.add_user(@u1)
|
||||
@group.add_user(@u2)
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
@section1 = @course.course_sections.create!(name: 'Section One')
|
||||
@section2 = @course.course_sections.create!(name: 'Section Two')
|
||||
|
||||
if opts[:ta]
|
||||
@ta = course_with_ta(course: @course, active_all: true).user
|
||||
def setup_assignment_without_submission
|
||||
assignment_model(:course => @course)
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
@student1, @student2, @student3 = create_users(3, return_type: :record)
|
||||
student_in_section(@section1, user: @student1)
|
||||
student_in_section(@section2, user: @student2)
|
||||
def setup_assignment_with_homework
|
||||
setup_assignment_without_submission
|
||||
res = @assignment.submit_homework(@user, {:submission_type => 'online_text_entry', :body => 'blah'})
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
@assignment = assignment_model(course: @course, submission_types: "online_url", workflow_state: "published")
|
||||
@override_s1 = differentiated_assignment(assignment: @assignment, course_section: @section1)
|
||||
@override_s1.due_at = 1.day.from_now
|
||||
@override_s1.save!
|
||||
def setup_assignment_with_students
|
||||
@graded_notify = Notification.create!(:name => "Submission Graded")
|
||||
@grade_change_notify = Notification.create!(:name => "Submission Grade Changed")
|
||||
@stu1 = @student
|
||||
@course.enroll_student(@stu2 = user_factory)
|
||||
@assignment = @course.assignments.create(:title => "asdf", :points_possible => 10)
|
||||
@sub1 = @assignment.grade_student(@stu1, grade: 9, grader: @teacher).first
|
||||
@assignment.reload
|
||||
end
|
||||
|
||||
def submit_homework(student)
|
||||
file_context = @assignment.group_category.group_for(student) if @assignment.has_group_category?
|
||||
file_context ||= student
|
||||
a = Attachment.create! context: file_context,
|
||||
filename: "homework.pdf",
|
||||
uploaded_data: StringIO.new("blah blah blah")
|
||||
@assignment.submit_homework(student, attachments: [a],
|
||||
submission_type: "online_upload")
|
||||
a
|
||||
end
|
||||
|
||||
def zip_submissions
|
||||
zip = Attachment.new filename: 'submissions.zip'
|
||||
zip.user = @teacher
|
||||
zip.workflow_state = 'to_be_zipped'
|
||||
zip.context = @assignment
|
||||
zip.save!
|
||||
ContentZipper.process_attachment(zip, @teacher)
|
||||
raise "zip failed" if zip.workflow_state != "zipped"
|
||||
zip
|
||||
end
|
||||
|
||||
def setup_differentiated_assignments(opts={})
|
||||
if !opts[:course]
|
||||
course_with_teacher(active_all: true)
|
||||
end
|
||||
|
||||
@section1 = @course.course_sections.create!(name: 'Section One')
|
||||
@section2 = @course.course_sections.create!(name: 'Section Two')
|
||||
|
||||
if opts[:ta]
|
||||
@ta = course_with_ta(course: @course, active_all: true).user
|
||||
end
|
||||
|
||||
@student1, @student2, @student3 = create_users(3, return_type: :record)
|
||||
student_in_section(@section1, user: @student1)
|
||||
student_in_section(@section2, user: @student2)
|
||||
|
||||
@assignment = assignment_model(course: @course, submission_types: "online_url", workflow_state: "published")
|
||||
@override_s1 = differentiated_assignment(assignment: @assignment, course_section: @section1)
|
||||
@override_s1.due_at = 1.day.from_now
|
||||
@override_s1.save!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#
|
||||
# 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 "Broadcast Policies" do
|
||||
it "should send a notification when a new announcement is created" do
|
||||
|
||||
end
|
||||
end
|
|
@ -401,7 +401,7 @@ describe ConditionalRelease::Service do
|
|||
context 'assignment data' do
|
||||
before(:each) do
|
||||
allow(Service).to receive(:enabled_in_context?).and_return(true)
|
||||
expect(CanvasHttp).to receive(:get).once.
|
||||
allow(CanvasHttp).to receive(:get).once.
|
||||
and_return(double({ code: '200', body: default_rules.to_json }))
|
||||
end
|
||||
|
||||
|
@ -530,7 +530,7 @@ describe ConditionalRelease::Service do
|
|||
|
||||
it 'returns a list of rules' do
|
||||
expect_cyoe_request '200', @a1
|
||||
expect(rules.length > 0)
|
||||
expect(rules.length).to be > 0
|
||||
expect(models0).to eq [@a1]
|
||||
end
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@ shared_examples_for "course copy" do
|
|||
yield(export) if block_given?
|
||||
export.save
|
||||
export.export_course
|
||||
expect(export.workflow_state).to eq 'exported'
|
||||
expect(export.attachment_id).not_to be_nil
|
||||
export
|
||||
end
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@ describe ContextExternalTool do
|
|||
@root_account = @course.root_account
|
||||
@account = account_model(:root_account => @root_account, :parent_account => @root_account)
|
||||
@course.update_attribute(:account, @account)
|
||||
expect(@course.account).to eql(@account)
|
||||
expect(@course.root_account).to eql(@root_account)
|
||||
expect(@account.parent_account).to eql(@root_account)
|
||||
expect(@account.root_account).to eql(@root_account)
|
||||
end
|
||||
|
||||
describe '#content_migration_configured?' do
|
||||
|
|
|
@ -1050,9 +1050,6 @@ describe ContextModule do
|
|||
{id: @other_assignment_tag.id, type: 'min_score', min_score: 90},
|
||||
]
|
||||
@module.save!
|
||||
|
||||
expect(@module.completion_requirements.include?({id: @assignment_tag.id, type: 'min_score', min_score: 90})).to be_truthy
|
||||
expect(@module.completion_requirements.include?({id: @other_assignment_tag.id, type: 'min_score', min_score: 90})).to be_truthy
|
||||
end
|
||||
|
||||
it 'should not prevent a student from completing a module' do
|
||||
|
|
|
@ -821,10 +821,6 @@ describe Conversation do
|
|||
ConversationMessageParticipant.update_all "tags = NULL"
|
||||
|
||||
@conversation = Conversation.find(@conversation.id)
|
||||
expect(@conversation.tags).to eql []
|
||||
expect(@u1.conversations.first.tags).to eql []
|
||||
expect(@u2.conversations.first.tags).to eql []
|
||||
expect(@u3.conversations.first.tags).to eql []
|
||||
end
|
||||
|
||||
it "should set the default tags when migrating" do
|
||||
|
|
|
@ -39,7 +39,6 @@ class Enrollment
|
|||
before(:once) { course_with_student(:active_all => 1) }
|
||||
let(:recent_activity) { Enrollment::RecentActivity.new(@enrollment) }
|
||||
let(:now){ Time.zone.now }
|
||||
before(:each){ expect(@enrollment.last_activity_at).to be_nil }
|
||||
|
||||
describe "#record!" do
|
||||
it "should record on the first call (last_activity_at is nil)" do
|
||||
|
|
|
@ -992,7 +992,6 @@ describe Enrollment do
|
|||
describe 'term dates' do
|
||||
before do
|
||||
@term = @course.enrollment_term
|
||||
expect(@term).to_not be_nil
|
||||
end
|
||||
|
||||
it "should return active" do
|
||||
|
@ -1042,7 +1041,6 @@ describe Enrollment do
|
|||
describe 'enrollment_dates_override dates' do
|
||||
before do
|
||||
@term = @course.enrollment_term
|
||||
expect(@term).to_not be_nil
|
||||
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => @enrollment.type, :enrollment_term => @term)
|
||||
end
|
||||
|
||||
|
@ -1099,7 +1097,6 @@ describe Enrollment do
|
|||
describe 'section dates' do
|
||||
before do
|
||||
@section = @course.course_sections.first
|
||||
expect(@section).to_not be_nil
|
||||
@section.restrict_enrollments_to_section_dates = true
|
||||
end
|
||||
|
||||
|
@ -1915,8 +1912,8 @@ describe Enrollment do
|
|||
describe "effective_start_at" do
|
||||
before :once do
|
||||
course_with_student(:active_all => true)
|
||||
expect(@term = @course.enrollment_term).not_to be_nil
|
||||
expect(@section = @enrollment.course_section).not_to be_nil
|
||||
@term = @course.enrollment_term
|
||||
@section = @enrollment.course_section
|
||||
|
||||
# 7 different possible times, make sure they're distinct
|
||||
@enrollment_date_start_at = 7.days.ago
|
||||
|
@ -1974,8 +1971,8 @@ describe Enrollment do
|
|||
describe "effective_end_at" do
|
||||
before :once do
|
||||
course_with_student(:active_all => true)
|
||||
expect(@term = @course.enrollment_term).not_to be_nil
|
||||
expect(@section = @enrollment.course_section).not_to be_nil
|
||||
@term = @course.enrollment_term
|
||||
@section = @enrollment.course_section
|
||||
|
||||
# 5 different possible times, make sure they're distinct
|
||||
@enrollment_date_end_at = 1.days.ago
|
||||
|
|
|
@ -235,7 +235,6 @@ describe ModeratedGrading::ProvisionalGrade do
|
|||
:assessment => { :assessment_type => 'grading',
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => { :points => 3, :comments => "wat" } })
|
||||
@prov_comment = @sub.add_comment(:commenter => @scorer, :comment => 'blah', :provisional => true)
|
||||
expect(@prov_comment.provisional_grade_id).to eq @pg.id
|
||||
end
|
||||
|
||||
def test_copy_to_final_mark
|
||||
|
|
|
@ -184,7 +184,6 @@ describe Quizzes::QuizQuestionLinkMigrator do
|
|||
context "with assessment questions" do
|
||||
before :once do
|
||||
@question = @quiz.quiz_questions.create!(:question_data => {:question_type => :multiple_choice})
|
||||
expect(@question.assessment_question).not_to be_nil
|
||||
end
|
||||
|
||||
let_once(:file) do
|
||||
|
|
|
@ -2038,10 +2038,6 @@ describe Quizzes::Quiz do
|
|||
end
|
||||
|
||||
context 'assignment is not locked' do
|
||||
before do
|
||||
expect(assignment_lock_info).not_to be_present
|
||||
end
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
|
|
|
@ -31,21 +31,17 @@ describe Quizzes::QuizSubmissionHistory do
|
|||
@submission.score = 5.0
|
||||
@submission.attempt = 1
|
||||
@submission.with_versioning(true, &:save!)
|
||||
expect(@submission.version_number).to eql(1)
|
||||
expect(@submission.score).to eql(5.0)
|
||||
|
||||
# regrade 1
|
||||
@submission.score_before_regrade = 5.0
|
||||
@submission.score = 4.0
|
||||
@submission.attempt = 1
|
||||
@submission.with_versioning(true, &:save!)
|
||||
expect(@submission.version_number).to eql(2)
|
||||
|
||||
# new attempt
|
||||
@submission.score = 3.0
|
||||
@submission.attempt = 2
|
||||
@submission.with_versioning(true, &:save!)
|
||||
expect(@submission.version_number).to eql(3)
|
||||
end
|
||||
|
||||
describe "#initialize" do
|
||||
|
|
|
@ -285,7 +285,7 @@ describe Quizzes::QuizSubmissionService do
|
|||
|
||||
context 'as a teacher' do
|
||||
before :each do
|
||||
expect(qs).to receive(:grants_right?).with(participant.user, :update_scores).and_return true
|
||||
allow(qs).to receive(:grants_right?).with(participant.user, :update_scores).and_return true
|
||||
end
|
||||
|
||||
def expect_version_object
|
||||
|
@ -373,7 +373,7 @@ describe Quizzes::QuizSubmissionService do
|
|||
|
||||
context 'as someone else' do
|
||||
before :each do
|
||||
expect(qs).to receive(:grants_right?).with(participant.user, :update_scores).and_return false
|
||||
allow(qs).to receive(:grants_right?).with(participant.user, :update_scores).and_return false
|
||||
end
|
||||
|
||||
it 'should deny access' do
|
||||
|
|
|
@ -1135,13 +1135,11 @@ describe Quizzes::QuizSubmission do
|
|||
s.score = 10
|
||||
s.save(:validate => false)
|
||||
end
|
||||
expect(submission.version_number).to eq 1
|
||||
|
||||
submission.with_versioning(true) do |s|
|
||||
s.score = 15
|
||||
s.save(:validate => false)
|
||||
end
|
||||
expect(submission.version_number).to eq 2
|
||||
end
|
||||
|
||||
it "updates a previous version given current attributes" do
|
||||
|
@ -1350,8 +1348,6 @@ describe Quizzes::QuizSubmission do
|
|||
@submission.score = 5.0
|
||||
@submission.attempt = 1
|
||||
@submission.with_versioning(true, &:save!)
|
||||
expect(@submission.version_number).to eql(1)
|
||||
expect(@submission.score).to eql(5.0)
|
||||
@submission.save
|
||||
end
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ describe Setting do
|
|||
context "setting" do
|
||||
|
||||
it 'should set values as strings' do
|
||||
expect(Setting.set('my_new_setting', true))
|
||||
Setting.set('my_new_setting', true)
|
||||
expect(Setting.get('my_new_setting', '1')).to eq 'true'
|
||||
end
|
||||
|
||||
it 'should set values as strings' do
|
||||
time = Time.now.utc
|
||||
expect(Setting.set('my_new_setting', time))
|
||||
Setting.set('my_new_setting', time)
|
||||
expect(Setting.get('my_new_setting', '1')).to eq time.to_s
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,14 +40,11 @@ describe SisBatch do
|
|||
end
|
||||
end
|
||||
|
||||
old_job_count = sis_jobs.count
|
||||
batch = File.open(path, 'rb') do |tmp|
|
||||
# arrrgh attachment.rb
|
||||
def tmp.original_filename; File.basename(path); end
|
||||
SisBatch.create_with_attachment(@account, 'instructure_csv', tmp, @user || user_factory)
|
||||
end
|
||||
# SisBatches shouldn't need any background processing
|
||||
expect(sis_jobs.count).to eq old_job_count
|
||||
yield batch if block_given?
|
||||
batch
|
||||
end
|
||||
|
@ -153,7 +150,6 @@ test_1,TC 101,Test Course 101,,term1,deleted
|
|||
}
|
||||
|
||||
before do
|
||||
expect(@account).to respond_to(:update_account_associations)
|
||||
track_jobs { job.reschedule }
|
||||
end
|
||||
|
||||
|
|
|
@ -24,14 +24,9 @@ describe StudentEnrollment do
|
|||
@student = User.create(:name => "some student")
|
||||
@course = Course.create(:name => "some course")
|
||||
@se = @course.enroll_student(@student)
|
||||
expect(@se.user_id).to eql(@student.id)
|
||||
expect(@course.students).to include(@student)
|
||||
@assignment = @course.assignments.create!(:title => 'some assignment')
|
||||
expect(@course.assignments).to include(@assignment)
|
||||
@submission = @assignment.submit_homework(@student)
|
||||
@assignment.reload
|
||||
expect(@submission).not_to be_nil
|
||||
expect(@assignment.submissions.to_a).to eql([@submission])
|
||||
@course.save!
|
||||
@se = @course.student_enrollments.first
|
||||
end
|
||||
|
|
|
@ -24,14 +24,9 @@ describe StudentViewEnrollment do
|
|||
@student = User.create(:name => "some student")
|
||||
@course = Course.create(:name => "some course")
|
||||
@se = @course.enroll_student(@student)
|
||||
expect(@se.user_id).to eql(@student.id)
|
||||
expect(@course.students).to include(@student)
|
||||
@assignment = @course.assignments.create!(:title => 'some assignment')
|
||||
expect(@course.assignments).to include(@assignment)
|
||||
@submission = @assignment.submit_homework(@student)
|
||||
@assignment.reload
|
||||
expect(@submission).not_to be_nil
|
||||
expect(@assignment.submissions.to_a).to eql([@submission])
|
||||
@course.save!
|
||||
@se = @course.student_enrollments.first
|
||||
end
|
||||
|
|
|
@ -2454,12 +2454,9 @@ describe Submission do
|
|||
expect(Submission.needs_grading.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def submission_spec_model(opts={})
|
||||
@submission = Submission.new(@valid_attributes.merge(opts))
|
||||
expect(@submission.assignment).to eql(@assignment)
|
||||
expect(@assignment.context).to eql(@context)
|
||||
expect(@submission.assignment.context).to eql(@context)
|
||||
@submission.save!
|
||||
def submission_spec_model(opts={})
|
||||
@submission = Submission.new(@valid_attributes.merge(opts))
|
||||
@submission.save!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -132,7 +132,6 @@ describe UserObserver do
|
|||
@observer = user_with_pseudonym
|
||||
student.observers << @observer
|
||||
@observer_enrollment = @observer.enrollments.where(type: 'ObserverEnrollment', course_id: @course, associated_user_id: student).first
|
||||
expect(@observer_enrollment).not_to be_nil
|
||||
end
|
||||
|
||||
it "should not attempt to add a duplicate observer enrollment" do
|
||||
|
|
|
@ -117,7 +117,7 @@ describe "add_people" do
|
|||
|
||||
# check the checkbox
|
||||
f('label[for="limit_privileges_to_course_section"]').click
|
||||
expect(f('#limit_privileges_to_course_section').selected?)
|
||||
expect(f('#limit_privileges_to_course_section')).to be_selected
|
||||
|
||||
# cancel the dialog
|
||||
f('#addpeople_cancel').click
|
||||
|
@ -129,7 +129,7 @@ describe "add_people" do
|
|||
|
||||
# check the checkbox again
|
||||
f('label[for="limit_privileges_to_course_section"]').click
|
||||
expect(f('#limit_privileges_to_course_section').selected?)
|
||||
expect(f('#limit_privileges_to_course_section')).to be_selected
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -241,8 +241,8 @@ describe "admin settings tab" do
|
|||
|
||||
before(:each) do
|
||||
f("#enable_equella").click
|
||||
expect(is_checked("#enable_equella")).to be_truthy
|
||||
end
|
||||
|
||||
it "should add an equella feature" do
|
||||
add_equella_feature
|
||||
end
|
||||
|
|
|
@ -41,13 +41,10 @@ describe "site admin jobs ui" do
|
|||
all_jobs.each { |job| expect(job).to have_class('selected') }
|
||||
end
|
||||
|
||||
def first_jobs_cell_displayed?
|
||||
expect(f('#jobs-grid .slick-cell')).to be
|
||||
end
|
||||
|
||||
def load_jobs_page
|
||||
get "/jobs"
|
||||
first_jobs_cell_displayed?
|
||||
# wait for it
|
||||
f('#jobs-grid .slick-cell')
|
||||
end
|
||||
|
||||
def filter_jobs(job_flavor_text)
|
||||
|
|
|
@ -46,8 +46,6 @@ describe "admin_tools" do
|
|||
def click_view_tab(tab_name)
|
||||
wait_for_ajaximations
|
||||
tab = fj("#adminToolsTabs .#{tab_name} > a")
|
||||
expect(tab).not_to be_nil
|
||||
expect(tab).to be_displayed
|
||||
tab.click
|
||||
wait_for_ajaximations
|
||||
end
|
||||
|
|
|
@ -71,7 +71,7 @@ describe "collaborations" do
|
|||
user_session(@student)
|
||||
get "/courses/#{@course.id}/collaborations"
|
||||
|
||||
ff('#collaborations .collaboration').length == 1
|
||||
expect(ff('#collaborations .collaboration')).to have_size(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,14 +66,14 @@ describe "collaborations" do
|
|||
all_icons.last.click
|
||||
driver.switch_to.alert.accept
|
||||
wait_for_ajaximations
|
||||
expect(check_element_has_focus(all_icons.first))
|
||||
expect(check_element_has_focus(all_icons.first)).to be
|
||||
end
|
||||
|
||||
it 'should set focus to the add collaboration button if there are no previous collaborations' do
|
||||
f('.delete_collaboration_link').click
|
||||
driver.switch_to.alert.accept
|
||||
wait_for_ajaximations
|
||||
expect(check_element_has_focus(f('.add_collaboration_link')))
|
||||
expect(check_element_has_focus(f('.add_collaboration_link'))).to be
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,6 +117,12 @@ shared_context "in-process server selenium tests" do
|
|||
driver.ready_for_interaction = false # need to `get` before we do anything selenium-y in a spec
|
||||
end
|
||||
|
||||
around :all do |group|
|
||||
GreatExpectations.with_config(MISSING: :raise) do
|
||||
group.run_examples
|
||||
end
|
||||
end
|
||||
|
||||
append_before :all do
|
||||
retry_count = 0
|
||||
begin
|
||||
|
|
|
@ -40,8 +40,10 @@ describe 'Web conferences' do
|
|||
|
||||
context 'when concluding a conference' do
|
||||
let(:conference_title) { 'Newer Conference' }
|
||||
before(:once) { create_wimba_conference(conference_title) }
|
||||
before(:each) { start_first_conference_in_list }
|
||||
before(:once) do
|
||||
conference = create_wimba_conference(conference_title)
|
||||
conference.add_attendee(@user)
|
||||
end
|
||||
|
||||
context 'as a teacher' do
|
||||
it 'concludes the conference', priority: "1", test_id: 323320 do
|
||||
|
|
|
@ -655,17 +655,15 @@ describe "context modules" do
|
|||
context "module item cog focus management", priority: "1" do
|
||||
|
||||
before :each do
|
||||
create_modules(1)[0].add_item({id: @assignment.id, type: 'assignment'})
|
||||
get "/courses/#{@course.id}/modules"
|
||||
add_existing_module_item('#assignments_select', 'Assignment', @assignment.title)
|
||||
@tag = ContentTag.last
|
||||
f("#context_module_item_#{@tag.id} .al-trigger").click
|
||||
end
|
||||
|
||||
it "should return focus to the cog menu when closing the edit dialog for an item" do
|
||||
hover_and_click("#context_module_item_#{@tag.id} .edit_item_link")
|
||||
cancel_buttons = ff('.cancel_button.ui-button')
|
||||
expect(cancel_buttons).to have_size(2)
|
||||
cancel_buttons[1].click
|
||||
f('.cancel_button.ui-button').click
|
||||
check_element_has_focus(fj("#context_module_item_#{@tag.id} .al-trigger"))
|
||||
end
|
||||
|
||||
|
|
|
@ -79,6 +79,12 @@ describe "conversations new" do
|
|||
wait_for_ajaximations
|
||||
select_message_course(@group, true)
|
||||
add_message_recipient @s2
|
||||
write_message_subject('blah')
|
||||
write_message_body('bluh')
|
||||
click_send
|
||||
run_jobs
|
||||
conv = @s2.conversations.last.conversation
|
||||
expect(conv.subject).to eq 'blah'
|
||||
end
|
||||
|
||||
it "should allow messages to be sent individually for account-level groups", priority: "2", test_id: 201506 do
|
||||
|
@ -261,7 +267,7 @@ describe "conversations new" do
|
|||
fj('.btn.dropdown-toggle :contains("Select course")').click
|
||||
wait_for_ajaximations
|
||||
|
||||
expect(f('.dropdown-menu.open')).to be_truthy
|
||||
f('.dropdown-menu.open')
|
||||
|
||||
fj('.message-header-input .text:contains("Unnamed Course")').click
|
||||
wait_for_ajaximations
|
||||
|
@ -318,7 +324,7 @@ describe "conversations new" do
|
|||
wait_for_ajaximations
|
||||
f('.icon-compose').click
|
||||
wait_for_ajaximations
|
||||
expect(f("#compose-new-message")).to be_present
|
||||
f("#compose-new-message")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -169,12 +169,12 @@ describe "course copy" do
|
|||
before(:each) do
|
||||
course_with_admin_logged_in
|
||||
@date_to_use = 2.weeks.from_now.monday.strftime("%Y-%m-%d")
|
||||
get "/calendar"
|
||||
quick_jump_to_date(@date_to_use)
|
||||
create_calendar_event('Monday Event', true, false, false, @date_to_use, true)
|
||||
end
|
||||
|
||||
it "shifts the dates a week later", priority: "2", test_id: 2953906 do
|
||||
get "/calendar"
|
||||
quick_jump_to_date(@date_to_use)
|
||||
create_calendar_event('Monday Event', true, false, false, @date_to_use, true)
|
||||
get "/courses/#{@course.id}/copy"
|
||||
new_course_name = "copied course"
|
||||
replace_content(f("input[type=text][id=course_name]"), new_course_name)
|
||||
|
@ -184,8 +184,7 @@ describe "course copy" do
|
|||
replace_content(f("input[type=text][id=newStartDate]"), date)
|
||||
submit_form('#copy_course_form')
|
||||
run_jobs
|
||||
status = f('div.progressStatus span').text
|
||||
keep_trying_until { expect(status == 'Completed') }
|
||||
expect(f('div.progressStatus span')).to include_text 'Completed'
|
||||
get "/calendar#view_name=week"
|
||||
quick_jump_to_date(@date_to_use)
|
||||
f('.fc-event').click
|
||||
|
|
|
@ -22,13 +22,11 @@ describe "discussion assignments" do
|
|||
|
||||
context "create group discussion" do
|
||||
before do
|
||||
get "/courses/#{@course.id}/discussion_topics"
|
||||
expect_new_page_load{f("#new-discussion-btn").click}
|
||||
get "/courses/#{@course.id}/discussion_topics/new"
|
||||
f("#discussion-title").send_keys("New Discussion Title")
|
||||
type_in_tiny('textarea[name=message]', 'Discussion topic message body')
|
||||
f("#has_group_category").click
|
||||
drop_down = get_options('#assignment_group_category_id').map(&:text).map(&:strip)
|
||||
expect(drop_down).to include('category 1')
|
||||
click_option('#assignment_group_category_id', 'category 1')
|
||||
end
|
||||
|
||||
|
|
|
@ -11,8 +11,7 @@ describe "add content box" do
|
|||
@assignment.submit_homework(@student)
|
||||
attachment_model(:context => @student)
|
||||
eportfolio_model({:user => @user, :name => "student content"})
|
||||
get "/eportfolios/#{@eportfolio.id}"
|
||||
expect_new_page_load { f(".icon-arrow-right").click }
|
||||
get "/eportfolios/#{@eportfolio.id}?view=preview"
|
||||
f("#right-side .edit_content_link").click
|
||||
wait_for_ajaximations
|
||||
end
|
||||
|
|
|
@ -60,7 +60,7 @@ module Gradebook
|
|||
period = gp_menu_list.find do |item|
|
||||
f('label', item).attribute("for") == "period_option_#{grading_period_id}"
|
||||
end
|
||||
expect_new_page_load { period.click }
|
||||
wait_for_new_page_load { period.click } or raise "page not loaded"
|
||||
end
|
||||
|
||||
def enter_grade(grade, x_coordinate, y_coordinate)
|
||||
|
|
|
@ -40,7 +40,7 @@ module Gradezilla
|
|||
period = gp_menu_list.find do |item|
|
||||
f('label', item).attribute("for") == "period_option_#{grading_period_id}"
|
||||
end
|
||||
expect_new_page_load { period.click }
|
||||
wait_for_new_page_load { period.click } or raise "page not loaded"
|
||||
end
|
||||
|
||||
def enter_grade(grade, x_coordinate, y_coordinate)
|
||||
|
|
|
@ -349,7 +349,6 @@ describe 'Speedgrader' do
|
|||
user_session(@teacher)
|
||||
# see first student
|
||||
get "/courses/#{@course.id}/gradebook/speed_grader?assignment_id=#{@assignment.id}"
|
||||
expect(Speedgrader.selected_student).to include_text(@students[0].name)
|
||||
end
|
||||
|
||||
after :each do
|
||||
|
@ -359,26 +358,30 @@ describe 'Speedgrader' do
|
|||
let(:next_) {'.next'}
|
||||
let(:previous) {'.prev'}
|
||||
|
||||
it 'selects the first student' do
|
||||
expect(Speedgrader.selected_student).to include_text(@students[0].name)
|
||||
end
|
||||
|
||||
it 'has working next and previous arrows ', priority: "1", test_id: 164018 do
|
||||
# click next to second student
|
||||
expect(cycle_students_correctly(next_))
|
||||
expect(cycle_students_correctly(next_)).to be
|
||||
|
||||
# click next to third student
|
||||
expect(cycle_students_correctly(next_))
|
||||
expect(cycle_students_correctly(next_)).to be
|
||||
|
||||
# go bak to the first student
|
||||
expect(cycle_students_correctly(previous))
|
||||
# go back to the first student
|
||||
expect(cycle_students_correctly(previous)).to be
|
||||
end
|
||||
|
||||
it 'arrows wrap around to start when you reach the last student', priority: "1", test_id: 272512 do
|
||||
# click next to second student
|
||||
expect(cycle_students_correctly(next_))
|
||||
expect(cycle_students_correctly(next_)).to be
|
||||
|
||||
# click next to third student
|
||||
expect(cycle_students_correctly(next_))
|
||||
expect(cycle_students_correctly(next_)).to be
|
||||
|
||||
# wrap around to the first student
|
||||
expect(cycle_students_correctly(next_))
|
||||
expect(cycle_students_correctly(next_)).to be
|
||||
end
|
||||
|
||||
it 'list all students', priority: "1", test_id: 164206 do
|
||||
|
|
|
@ -1000,7 +1000,7 @@ describe "new groups" do
|
|||
|
||||
select_change_groups_option
|
||||
|
||||
expect(f('.progressbar').displayed?)
|
||||
expect(f('.progressbar')).to be_displayed
|
||||
end
|
||||
|
||||
context "dragging and dropping a student" do
|
||||
|
|
|
@ -8,18 +8,10 @@ module ConferencesCommon
|
|||
f('.new-conference-btn')
|
||||
end
|
||||
|
||||
def start_conference_button
|
||||
f('.start-button', new_conference_list)
|
||||
end
|
||||
|
||||
def end_conference_button
|
||||
f('.close_conference_link', new_conference_list)
|
||||
end
|
||||
|
||||
def start_first_conference_in_list
|
||||
expect_new_page_load { start_conference_button.click }
|
||||
end
|
||||
|
||||
def end_first_conference_in_list
|
||||
end_conference_button.click
|
||||
close_modal_if_present
|
||||
|
|
|
@ -90,9 +90,7 @@ module ContextModulesCommon
|
|||
fj('.add_item_button.ui-button').click
|
||||
wait_for_ajaximations
|
||||
tag = ContentTag.last
|
||||
module_item = f("#context_module_item_#{tag.id}")
|
||||
expect(module_item).to include_text(item_name)
|
||||
module_item
|
||||
fj("#context_module_item_#{tag.id}:contains(#{item_name.inspect})")
|
||||
end
|
||||
|
||||
def select_module_item(select_element_css, item_text)
|
||||
|
@ -100,11 +98,8 @@ module ContextModulesCommon
|
|||
end
|
||||
|
||||
def new_module_form
|
||||
add_form = f('#add_context_module_form')
|
||||
f(".add_module_link").click
|
||||
expect(add_form).to be_displayed
|
||||
|
||||
add_form
|
||||
fj('#add_context_module_form:visible')
|
||||
end
|
||||
|
||||
def add_module(module_name = 'Test Module')
|
||||
|
|
|
@ -304,7 +304,7 @@ module GroupsCommon
|
|||
def verify_member_sees_group_page(index = 0)
|
||||
get pages_page
|
||||
expect_new_page_load { ff('.wiki-page-link')[index].click }
|
||||
expect expect(f('.page-title')).to include_text("#{@page.title}")
|
||||
expect(f('.page-title')).to include_text(@page.title)
|
||||
end
|
||||
|
||||
# context test. if true, allows you to test files both in and out of group context,
|
||||
|
|
|
@ -349,11 +349,11 @@ module QuizzesCommon
|
|||
end
|
||||
|
||||
if access_code.nil?
|
||||
expect_new_page_load { f('#take_quiz_link').click }
|
||||
wait_for_new_page_load { f('#take_quiz_link').click }
|
||||
else
|
||||
f('#quiz_access_code').send_keys(access_code)
|
||||
expect_new_page_load { fj('.btn', '#main').click }
|
||||
end
|
||||
wait_for_new_page_load { fj('.btn', '#main').click }
|
||||
end or raise "unable to start quiz"
|
||||
|
||||
wait_for_quiz_to_begin
|
||||
end
|
||||
|
|
|
@ -126,7 +126,7 @@ module SchedulerCommon
|
|||
|
||||
def click_appointment_link
|
||||
f('.view_calendar_link').click
|
||||
expect(f('.agenda-wrapper.active')).to be_displayed
|
||||
fj('.agenda-wrapper.active:visible')
|
||||
wait_for_ajaximations
|
||||
end
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ module SpeedGraderCommon
|
|||
# move onto next student
|
||||
direction = direction_string.equal?(:next) ? 1 : -1
|
||||
new_index = (current_index + direction) % @students.length
|
||||
student_x_of_x_string = "Student #{new_index + 1} of #{@students.length}"
|
||||
student_x_of_x_string = "#{new_index + 1}/#{@students.length}"
|
||||
|
||||
Speedgrader.selected_student.text.include?(@students[new_index].name) &&
|
||||
Speedgrader.student_x_of_x_label.text.include?(student_x_of_x_string)
|
||||
|
|
|
@ -92,7 +92,7 @@ describe 'new ui' do
|
|||
get "/courses/#{@course.id}/files"
|
||||
add_folder
|
||||
# verifying new files folder icon css property still displays with new ui
|
||||
f('.media-object.ef-big-icon.FilesystemObjectThumbnail.mimeClass-folder').displayed?
|
||||
expect(f('.media-object.ef-big-icon.FilesystemObjectThumbnail.mimeClass-folder')).to be_displayed
|
||||
end
|
||||
|
||||
it 'should not override high contrast theme', priority: "2", test_id: 244898 do
|
||||
|
@ -123,7 +123,7 @@ describe 'new ui' do
|
|||
get "/courses/#{@course.id}/assignments/new"
|
||||
f('div#mceu_19.mce-widget.mce-btn').click
|
||||
wait_for_ajaximations
|
||||
f('.mathquill-toolbar-panes, .mathquill-tab-bar').displayed?
|
||||
expect(f('.mathquill-toolbar-panes, .mathquill-tab-bar')).to be_displayed
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -131,9 +131,7 @@ describe "account admin outcomes" do
|
|||
end
|
||||
|
||||
def click_on_state_standards
|
||||
top_level_groups = ff(".outcome-level .outcome-group")
|
||||
expect(top_level_groups.count).to eq 3
|
||||
top_level_groups[1].click
|
||||
fj(".outcome-level .outcome-group:eq(1)").click
|
||||
wait_for_ajaximations
|
||||
end
|
||||
|
||||
|
|
|
@ -94,57 +94,28 @@ describe 'creating a quiz' do
|
|||
context 'when on the quizzes index page' do
|
||||
before(:each) do
|
||||
get "/courses/#{@course.id}/quizzes"
|
||||
end
|
||||
|
||||
def create_new_quiz
|
||||
expect_new_page_load do
|
||||
f('.new-quiz-link').click
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates a quiz directly from the index page', priority: "1", test_id: 210055 do
|
||||
expect_new_page_load do
|
||||
click_save_settings_button
|
||||
end
|
||||
expect(f('#quiz_title')).to include_text 'Unnamed Quiz'
|
||||
expect do
|
||||
create_new_quiz
|
||||
end.to change{ Quizzes::Quiz.count }.by(1)
|
||||
end
|
||||
|
||||
it 'redirects to the correct quiz edit form', priority: "2", test_id: 399887 do
|
||||
create_new_quiz
|
||||
# check url
|
||||
expect(driver.current_url).to match %r{/courses/\d+/quizzes/\d+\/edit}
|
||||
|
||||
# check quiz id
|
||||
# The =~ operator compares the regex with the string.
|
||||
# The (?<quiz_id>(\d+)) part of the regex tells the =~ to assign
|
||||
# the value of the number found therein to the variable, quiz_id.
|
||||
%r courses/\d+/quizzes/(?<quiz_id>(\d+))/edit =~ driver.current_url
|
||||
expect(quiz_id.to_i).to be > 0
|
||||
expect(driver.current_url).to match %r{/courses/\d+/quizzes/#{Quizzes::Quiz.last.id}\/edit}
|
||||
end
|
||||
|
||||
it 'creates and previews a new quiz', priority: "1", test_id: 210056 do
|
||||
# input name and description then save quiz
|
||||
replace_content(f('#quiz_title'), 'new quiz')
|
||||
description_text = 'new description'
|
||||
expect(f('#quiz_description_ifr')).to be_displayed
|
||||
type_in_tiny '#quiz_description', description_text
|
||||
in_frame 'quiz_description_ifr' do
|
||||
expect(f('#tinymce')).to include_text(description_text)
|
||||
end
|
||||
|
||||
# add a question
|
||||
click_questions_tab
|
||||
click_new_question_button
|
||||
submit_form('.question_form')
|
||||
wait_for_ajaximations
|
||||
|
||||
# save the quiz
|
||||
expect_new_page_load do
|
||||
click_save_settings_button
|
||||
wait_for_ajaximations
|
||||
end
|
||||
wait_for_ajaximations
|
||||
|
||||
# check quiz preview
|
||||
f('#preview_quiz_button').click
|
||||
expect(f('#questions')).to be_present
|
||||
end
|
||||
# TODO: remove this from test-rail, this test is redundant
|
||||
it 'creates and previews a new quiz', priority: "1", test_id: 210056
|
||||
end
|
||||
|
||||
it 'inserts files using the rich content editor', priority: "1", test_id: 132545 do
|
||||
|
|
|
@ -277,15 +277,8 @@ describe 'quizzes question creation' do
|
|||
|
||||
# get focus out of tinymce to allow change event to propogate
|
||||
f(".question_header").click
|
||||
f('button.recompute_variables').click
|
||||
val = f('.variable .value').text.to_i
|
||||
expect(val <= 10 && val >= 0)
|
||||
recompute_button = f('button.recompute_variables')
|
||||
var_el = f('.variable .value')
|
||||
keep_trying_until do
|
||||
recompute_button.click
|
||||
var_el.text.to_i != val
|
||||
end
|
||||
recompute_button.click
|
||||
fj('.supercalc:visible').send_keys('x + y')
|
||||
f('button.save_formula_button').click
|
||||
# normally it's capped at 200 (to keep the yaml from getting crazy big)...
|
||||
|
@ -418,6 +411,7 @@ describe 'quizzes question creation' do
|
|||
type_in_tiny '.question:visible textarea.question_content', 'This is an essay question.'
|
||||
submit_form(fj('.question_form:visible'))
|
||||
wait_for_ajax_requests
|
||||
expect(Quizzes::QuizQuestion.where("question_data like '%This is an essay question%'")).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ module CustomPageLoaders
|
|||
close_modal_if_present
|
||||
wait_for_ajaximations
|
||||
else
|
||||
expect_new_page_load(true) do
|
||||
wait_for_new_page_load(true) do
|
||||
driver.get(app_url + link)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -214,7 +214,6 @@ module CustomSeleniumActions
|
|||
assert_can_switch_views!
|
||||
switch_editor_views(tiny_controlling_element)
|
||||
tiny_controlling_element.clear
|
||||
expect(tiny_controlling_element[:value]).to be_empty
|
||||
switch_editor_views(tiny_controlling_element)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,18 +80,26 @@ module CustomValidators
|
|||
expect(box[0]).to be_displayed
|
||||
end
|
||||
|
||||
def expect_new_page_load(accept_alert = false)
|
||||
def wait_for_new_page_load(accept_alert = false)
|
||||
driver.execute_script("window.INST = window.INST || {}; INST.still_on_old_page = true;")
|
||||
yield
|
||||
wait_for method: :expect_new_page_load do
|
||||
wait_for(method: :wait_for_new_page_load) do
|
||||
begin
|
||||
driver.execute_script("return window.INST && INST.still_on_old_page !== true;")
|
||||
rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnknownError
|
||||
raise unless accept_alert
|
||||
driver.switch_to.alert.accept
|
||||
end
|
||||
end or raise(RSpec::Expectations::ExpectationNotMetError, "expected new page load, none happened")
|
||||
end or return false
|
||||
wait_for_dom_ready
|
||||
wait_for_ajaximations
|
||||
true
|
||||
end
|
||||
|
||||
def expect_new_page_load(accept_alert = false)
|
||||
success = wait_for_new_page_load(accept_alert) do
|
||||
yield
|
||||
end
|
||||
expect(success).to be, "expected new page load, none happened"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ module SeleniumExtensions
|
|||
yield
|
||||
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
||||
raise unless finder_proc
|
||||
location = CallStackUtils.best_line_for($ERROR_INFO.backtrace, /test_setup/)
|
||||
location = CallStackUtils.best_line_for($ERROR_INFO.backtrace)
|
||||
$stderr.puts "WARNING: StaleElementReferenceError at #{location}, attempting to recover..."
|
||||
@id = finder_proc.call.ref
|
||||
retry
|
||||
|
|
|
@ -63,7 +63,7 @@ describe "Wiki pages and Tiny WYSIWYG editor features" do
|
|||
|
||||
f(".mce-i-bullist").click
|
||||
in_frame wiki_page_body_ifr_id do
|
||||
ff('#tinymce li').length == 3
|
||||
expect(ff('#tinymce li').length).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -85,7 +85,7 @@ describe "Wiki pages and Tiny WYSIWYG editor features" do
|
|||
|
||||
f('.mce-i-numlist').click
|
||||
in_frame wiki_page_body_ifr_id do
|
||||
ff('#tinymce li').length == 3
|
||||
expect(ff('#tinymce li').length).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
|||
# let/before/example
|
||||
BlankSlateProtection.truncate_all_tables! unless defined?(TestQueue::Runner::RSpec) # we do this in each runner
|
||||
BlankSlateProtection.install!
|
||||
GreatExpectations.install!
|
||||
|
||||
ActionView::TestCase::TestController.view_paths = ApplicationController.view_paths
|
||||
|
||||
|
@ -572,8 +573,8 @@ RSpec.configure do |config|
|
|||
|
||||
def process_csv_data_cleanly(*lines_or_opts)
|
||||
importer = process_csv_data(*lines_or_opts)
|
||||
expect(importer.errors).to eq []
|
||||
expect(importer.warnings).to eq []
|
||||
raise "csv errors" if importer.errors.present?
|
||||
raise "csv warning" if importer.warnings.present?
|
||||
end
|
||||
|
||||
def enable_cache(new_cache=:memory_store)
|
||||
|
@ -726,8 +727,6 @@ RSpec.configure do |config|
|
|||
skip "Please put valid S3 credentials in config/amazon_s3.yml"
|
||||
end
|
||||
end
|
||||
expect(Attachment.s3_storage?).to be true
|
||||
expect(Attachment.local_storage?).to be false
|
||||
end
|
||||
|
||||
def local_storage!
|
||||
|
@ -738,9 +737,6 @@ RSpec.configure do |config|
|
|||
model.stubs(:s3_storage?).returns(false)
|
||||
model.stubs(:local_storage?).returns(true)
|
||||
end
|
||||
|
||||
expect(Attachment.local_storage?).to be true
|
||||
expect(Attachment.s3_storage?).to be false
|
||||
end
|
||||
|
||||
def run_job(job)
|
||||
|
|
|
@ -6,7 +6,7 @@ module BlankSlateProtection
|
|||
return super unless BlankSlateProtection.enabled?
|
||||
return super if caller.grep(BlankSlateProtection.exempt_patterns).present?
|
||||
|
||||
location = CallStackUtils.best_line_for(caller).sub(/:in .*/, '')
|
||||
location = CallStackUtils.best_line_for(caller)
|
||||
if caller.grep(/_context_hooks/).present?
|
||||
$stderr.puts "\e[31mError: Don't create records inside `:all` hooks!"
|
||||
$stderr.puts "See: " + location + "\e[0m"
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
module CallStackUtils
|
||||
def self.best_line_for(call_stack, except = nil)
|
||||
def self.best_line_for(call_stack)
|
||||
line = CallStackUtils.prune_backtrace!(call_stack).first
|
||||
root = Rails.root.to_s + "/"
|
||||
lines = call_stack
|
||||
lines = lines.reject { |l| l =~ except } if except
|
||||
app_lines = lines.select { |s| s.starts_with?(root) }
|
||||
line = app_lines.grep(%r{_spec\.rb:}).first ||
|
||||
app_lines.grep(%r{/spec(_canvas?)/}).first ||
|
||||
app_lines.first ||
|
||||
lines.first
|
||||
line.sub(root, '')
|
||||
line.sub(root, '').sub(/:in .*/, '')
|
||||
end
|
||||
|
||||
# (re-)raise the exception while preserving its backtrace
|
||||
|
@ -16,16 +10,21 @@ module CallStackUtils
|
|||
super exception.class, exception.message, exception.backtrace
|
||||
end
|
||||
|
||||
def self.prune_backtrace!(bt)
|
||||
line_regex = RSpec.configuration.in_project_source_dir_regex
|
||||
# remove things until we get to the frd error cause
|
||||
bt.shift while bt.first !~ line_regex || bt.first =~ %r{/spec/(support|selenium/test_setup/)}
|
||||
bt
|
||||
end
|
||||
|
||||
module ExceptionPresenter
|
||||
def exception_backtrace
|
||||
bt = super
|
||||
# for our custom matchers/validators/finders/etc., prune their lines
|
||||
# from the top of the stack so that you get a pretty/useful error
|
||||
# message and backtrace
|
||||
if exception_class_name =~ /\A(RSpec::|Selenium::WebDriver::Error::|SeleniumExtensions::)/
|
||||
line_regex = RSpec.configuration.in_project_source_dir_regex
|
||||
# remove things until we get to the frd error cause
|
||||
bt.shift while bt.first !~ line_regex || bt.first =~ %r{/spec/(support|selenium/test_setup/)}
|
||||
if exception_class_name =~ /\A(RSpec::|Selenium::WebDriver::Error::|SeleniumExtensions::|GreatExpectations::)/
|
||||
CallStackUtils.prune_backtrace! bt
|
||||
end
|
||||
bt
|
||||
end
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
# Ensure we aren't doing silly things with expectations, such as:
|
||||
#
|
||||
# 1. `expect` in a `before` ... `before` implies it's before the spec, so
|
||||
# why are you testing things there?
|
||||
# 2. `expect` without a `to` / `not_to` ... it will never get checked
|
||||
# 3. specs with no expectations... what's the point?
|
||||
|
||||
module GreatExpectations
|
||||
class Error < StandardError
|
||||
def self.for(message, location = nil)
|
||||
error = new(message)
|
||||
bt = caller
|
||||
# not a legit backtrace, but this way the rspec error/context
|
||||
# will point right at the example in the file
|
||||
bt.unshift "#{File.expand_path(location)}:in block in <top (required)>'" if location
|
||||
error.set_backtrace(bt)
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
# default behavior, can be overridden with `.with_config`
|
||||
CONFIG = {
|
||||
# what to do if there's an `expect` in a `before`
|
||||
EARLY: :raise,
|
||||
|
||||
# what to do if an `expect` has no `to`
|
||||
UNCHECKED: :raise,
|
||||
|
||||
# what to do if a spec has no `expect`s
|
||||
MISSING: :warn
|
||||
}.freeze
|
||||
|
||||
module Example
|
||||
# allow expectations at the last possible second (right after the
|
||||
# inner-most before hooks run)
|
||||
def run_before_example
|
||||
super
|
||||
GreatExpectations.example_started(self)
|
||||
end
|
||||
|
||||
# immediately before running any after hooks, ensure the spec had some
|
||||
# expectations. this includes mocha/rspec-mocks which will be verified
|
||||
# in the super call
|
||||
def run_after_example
|
||||
GreatExpectations.example_finished
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
module AssertionDelegator
|
||||
def assert(*)
|
||||
GreatExpectations.expectation_checked
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
module ExpectationTarget
|
||||
def initialize(*)
|
||||
GreatExpectations.expectation_created(self)
|
||||
super
|
||||
end
|
||||
|
||||
def to(*)
|
||||
GreatExpectations.expectation_checked(self)
|
||||
super
|
||||
end
|
||||
|
||||
def not_to(*)
|
||||
GreatExpectations.expectation_checked(self)
|
||||
super
|
||||
end
|
||||
alias to_not not_to
|
||||
end
|
||||
|
||||
class << self
|
||||
attr_accessor :config
|
||||
attr_accessor :current_example
|
||||
attr_accessor :expectation_count
|
||||
|
||||
def install!
|
||||
self.config = CONFIG
|
||||
::RSpec::Core::Example.prepend Example
|
||||
::RSpec::Expectations::ExpectationTarget.prepend ExpectationTarget
|
||||
::RSpec::Rails::MinitestAssertionAdapter::AssertionDelegator.prepend AssertionDelegator
|
||||
end
|
||||
|
||||
def with_config(config)
|
||||
orig_config = @config
|
||||
@config = orig_config.merge(config)
|
||||
yield
|
||||
ensure
|
||||
@config = orig_config
|
||||
end
|
||||
|
||||
def expectation_created(expectation)
|
||||
assert_not_early!
|
||||
unchecked_expectations << expectation
|
||||
end
|
||||
|
||||
def expectation_checked(expectation = nil)
|
||||
unchecked_expectations.delete(expectation) if expectation
|
||||
self.expectation_count += 1
|
||||
end
|
||||
|
||||
def unchecked_expectations
|
||||
@unchecked_expectations ||= Set.new
|
||||
end
|
||||
|
||||
def example_started(example)
|
||||
self.current_example = example
|
||||
self.expectation_count = 0
|
||||
end
|
||||
|
||||
def example_finished
|
||||
return if current_example.nil? || # like if we `skip` in a before
|
||||
current_example.exception ||
|
||||
current_example.skipped? ||
|
||||
current_example.pending?
|
||||
|
||||
assert_not_unchecked!
|
||||
assert_not_missing!
|
||||
rescue Error
|
||||
current_example.set_exception($ERROR_INFO)
|
||||
ensure
|
||||
self.current_example = nil
|
||||
unchecked_expectations.clear
|
||||
end
|
||||
|
||||
def assert_not_early!
|
||||
return if current_example
|
||||
generate_error config[:EARLY], "Don't `expect` outside of the spec itself. `before`/`after` should only be used for setup/teardown"
|
||||
end
|
||||
|
||||
def assert_not_unchecked!
|
||||
return if unchecked_expectations.empty?
|
||||
generate_error config[:UNCHECKED], "This spec has unchecked expectations, i.e. you forgot to call `to` or `not_to`", current_example.location
|
||||
end
|
||||
|
||||
def assert_not_missing!
|
||||
# vanilla expectation
|
||||
return if expectation_count > 0
|
||||
|
||||
# rspec message expectations
|
||||
return if ::RSpec::Mocks.space.proxies.any? do |_, proxy|
|
||||
proxy.instance_variable_get(:@method_doubles).any? do |_, double|
|
||||
double.expectations.any?
|
||||
end
|
||||
end
|
||||
return if ::RSpec::Mocks.space.any_instance_recorders.any? do |_, recorder|
|
||||
recorder.instance_variable_get(:@expectation_set)
|
||||
end
|
||||
|
||||
# mocha expectations
|
||||
return if ::Mocha::Mockery.instance.send(:expectations).any? do |expectation|
|
||||
expectation.instance_variable_get(:@cardinality).needs_verifying?
|
||||
end
|
||||
|
||||
generate_error config[:MISSING], "This spec has no expectations. Add one!", current_example.location
|
||||
end
|
||||
|
||||
def generate_error(action, message, location = nil)
|
||||
if action == :raise
|
||||
raise Error.for(message, location)
|
||||
else
|
||||
$stderr.puts "\e[31mWarning: #{message}"
|
||||
$stderr.puts "See: " + (location || CallStackUtils.best_line_for(caller)) + "\e[0m"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -102,7 +102,6 @@ describe "/courses/_recent_event" do
|
|||
@quiz.workflow_state = 'available'
|
||||
@quiz.published_at = Time.zone.now
|
||||
@quiz.save
|
||||
expect(@quiz.assignment).not_to be_nil
|
||||
|
||||
@quiz_submission = @quiz.generate_submission(@user)
|
||||
Quizzes::SubmissionGrader.new(@quiz_submission).grade_submission
|
||||
|
|
|
@ -56,8 +56,6 @@ describe "login/canvas/new.html.erb" do
|
|||
config.save!
|
||||
account.change_password_url = "http://www.instructure.com"
|
||||
account.save!
|
||||
expect(account.forgot_password_external_url).
|
||||
to eq(account.change_password_url)
|
||||
assigns[:domain_root_account] = account
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue