2020-10-27 00:51:19 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-07-20 01:31:02 +08:00
|
|
|
#
|
2017-04-28 12:12:06 +08:00
|
|
|
# Copyright (C) 2016 - present Instructure, Inc.
|
2016-07-20 01:31:02 +08:00
|
|
|
#
|
|
|
|
# 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 Score do
|
2017-08-17 21:47:36 +08:00
|
|
|
before(:once) do
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
@grading_periods = grading_periods
|
|
|
|
@assignment_group = test_course.assignment_groups.create!(name: "Assignments")
|
2017-08-17 21:47:36 +08:00
|
|
|
end
|
|
|
|
|
2016-07-20 01:31:02 +08:00
|
|
|
let(:test_course) { Course.create! }
|
|
|
|
let(:student) { student_in_course(course: test_course) }
|
2017-08-17 21:47:36 +08:00
|
|
|
let(:params) do
|
2016-07-20 01:31:02 +08:00
|
|
|
{
|
|
|
|
course: test_course,
|
|
|
|
current_score: 80.2,
|
|
|
|
final_score: 74.0,
|
|
|
|
updated_at: 1.week.ago
|
|
|
|
}
|
2017-08-17 21:47:36 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
let(:grading_period_score_params) do
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
params.merge(grading_period_id: @grading_periods.first.id)
|
2017-08-17 21:47:36 +08:00
|
|
|
end
|
|
|
|
let(:assignment_group_score_params) do
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
params.merge(assignment_group_id: @assignment_group.id)
|
2017-08-17 21:47:36 +08:00
|
|
|
end
|
|
|
|
let(:grading_period_score) { student.scores.create!(grading_period_score_params) }
|
|
|
|
let(:assignment_group_score) { student.scores.create!(assignment_group_score_params) }
|
|
|
|
|
2016-07-20 01:31:02 +08:00
|
|
|
subject_once(:score) { student.scores.create!(params) }
|
|
|
|
|
2019-07-09 04:35:56 +08:00
|
|
|
it { is_expected.to belong_to(:enrollment).required }
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
# shoulda-matchers will have an `optional` method in version 4. As a workaround,
|
|
|
|
# I've used the validates_presence_of matcher on the line following the belong_to matcher
|
|
|
|
it { is_expected.to belong_to(:grading_period) }
|
|
|
|
it { is_expected.not_to validate_presence_of(:grading_period) }
|
|
|
|
it { is_expected.to belong_to(:assignment_group) }
|
|
|
|
it { is_expected.not_to validate_presence_of(:assignment_group) }
|
|
|
|
it { is_expected.to have_one(:score_metadata) }
|
|
|
|
it { is_expected.to have_one(:course).through(:enrollment) }
|
|
|
|
|
2016-07-20 01:31:02 +08:00
|
|
|
it_behaves_like "soft deletion" do
|
|
|
|
subject { student.scores }
|
2017-08-17 21:47:36 +08:00
|
|
|
|
|
|
|
let(:creation_arguments) do
|
|
|
|
[
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
params.merge(grading_period: @grading_periods.first),
|
|
|
|
params.merge(grading_period: @grading_periods.last)
|
2017-08-17 21:47:36 +08:00
|
|
|
]
|
|
|
|
end
|
2016-07-20 01:31:02 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "validations" do
|
|
|
|
it { is_expected.to be_valid }
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
it { is_expected.to validate_numericality_of(:current_score).allow_nil }
|
|
|
|
it { is_expected.to validate_numericality_of(:unposted_current_score).allow_nil }
|
|
|
|
it { is_expected.to validate_numericality_of(:final_score).allow_nil }
|
|
|
|
it { is_expected.to validate_numericality_of(:unposted_final_score).allow_nil }
|
2016-07-20 01:31:02 +08:00
|
|
|
|
|
|
|
it "is invalid without an enrollment" do
|
|
|
|
score.enrollment = nil
|
|
|
|
expect(score).to be_invalid
|
|
|
|
end
|
|
|
|
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
it { is_expected.to validate_presence_of(:enrollment) }
|
|
|
|
|
2017-08-17 21:47:36 +08:00
|
|
|
it "is invalid without unique enrollment for course" do
|
2016-07-20 01:31:02 +08:00
|
|
|
student.scores.create!(params)
|
2017-08-17 21:47:36 +08:00
|
|
|
expect { student.scores.create!(params) }.to raise_error(ActiveRecord::RecordNotUnique)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is invalid without unique enrollment for grading period" do
|
|
|
|
student.scores.create!(grading_period_score_params)
|
|
|
|
expect { student.scores.create!(grading_period_score_params) }.to raise_error(ActiveRecord::RecordNotUnique)
|
|
|
|
end
|
|
|
|
|
2017-10-14 00:56:35 +08:00
|
|
|
it("is invalid without unique enrollment for assignment group") do
|
2017-08-17 21:47:36 +08:00
|
|
|
student.scores.create!(assignment_group_score_params)
|
|
|
|
expect { student.scores.create!(assignment_group_score_params) }.to raise_error(ActiveRecord::RecordNotUnique)
|
2016-07-20 01:31:02 +08:00
|
|
|
end
|
|
|
|
|
2017-10-14 00:56:35 +08:00
|
|
|
context("scorable associations") do
|
2017-08-17 21:47:36 +08:00
|
|
|
it "is valid with course_score true and no scorable associations" do
|
|
|
|
expect(student.scores.create!(course_score: true, **params)).to be_valid
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is valid with course_score false and a grading period association" do
|
|
|
|
expect(student.scores.create!(course_score: false, **grading_period_score_params)).to be_valid
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is valid with course_score false and an assignment group association" do
|
|
|
|
expect(student.scores.create!(course_score: false, **assignment_group_score_params)).to be_valid
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is invalid with course_score false and no scorable associations" do
|
|
|
|
expect do
|
|
|
|
score = student.scores.create!(params)
|
|
|
|
score.update!(course_score: false)
|
|
|
|
end.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is invalid with course_score true and a scorable association" do
|
|
|
|
expect do
|
|
|
|
student.scores.create!(course_score: true, **grading_period_score_params)
|
|
|
|
end.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is invalid with multiple scorable associations" do
|
|
|
|
expect do
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
student.scores.create!(grading_period_id: @grading_periods.first.id, **assignment_group_score_params)
|
2017-08-17 21:47:36 +08:00
|
|
|
end.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
|
|
|
end
|
2017-10-05 02:34:31 +08:00
|
|
|
end
|
|
|
|
|
2020-06-06 03:38:28 +08:00
|
|
|
describe "root_account_id" do
|
|
|
|
context "on create" do
|
|
|
|
it "sets root_account_id to the enrollment's root_account_id if root_account_id is nil" do
|
|
|
|
score = student.scores.create!(params)
|
|
|
|
expect(score.root_account_id).to eq student.root_account_id
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not modify root_account_id if it is already set" do
|
|
|
|
second_account = account_model
|
|
|
|
score = student.scores.create!(params.merge(root_account_id: second_account.id))
|
|
|
|
expect(score.root_account_id).to eq second_account.id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "on update" do
|
|
|
|
it "sets root_account_id to the enrollment's root_account_id if root_account_id is nil" do
|
|
|
|
score.update_column(:root_account_id, nil)
|
|
|
|
score.update!(current_score: 0)
|
|
|
|
expect(score.root_account_id).to eq student.root_account_id
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not modify root_account_id if it is already set" do
|
|
|
|
second_account = account_model
|
|
|
|
score.update!(root_account_id: second_account.id)
|
|
|
|
expect(score.root_account_id).to eq second_account.id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-05 02:34:31 +08:00
|
|
|
describe "#destroy" do
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
context "with score metadata" do
|
|
|
|
let(:metadata) { score.create_score_metadata!(calculation_details: { foo: :bar }) }
|
|
|
|
|
|
|
|
describe "score_metadata association" do
|
|
|
|
it "also destroys score metadata" do
|
|
|
|
metadata.score.destroy
|
|
|
|
expect(metadata).to be_deleted
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#destroy_permanently" do
|
|
|
|
context "with score metadata" do
|
|
|
|
let(:metadata) { score.create_score_metadata!(calculation_details: { foo: :bar }) }
|
|
|
|
|
|
|
|
describe "score_metadata association" do
|
|
|
|
it "also permanently destroys score metadata" do
|
|
|
|
metadata.score.destroy_permanently!
|
2018-07-28 05:27:54 +08:00
|
|
|
expect { metadata.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
make ScoreMetadata soft deleteable
This changeset will add the workflow_state column to score_metadata, add
a concurrent index to this column, and backfill nulls with 'active'. A
followup commit will add a not null constraint.
Other features include Score#destroy, Score#destroy_permanently!,
Score#undestroy all calling correspoding methods on the associated
ScoreMetadata, if present.
The shared examples for Soft::Deletion have been finished.
closes: GRADE-746
Test Plan
Part One: Verifying Migrations:
- after running the predeploy and before running the postdeploy,
create some score_metadata with workflow states that are nil,
'active', and 'deleted'. then, run the postdeploy.
- verify there are no null values for workflow_state in the
score_metadata table.
- verify that null values have been changed to 'active'.
- verify that all other values remain unchanged.
Part Two: Verifying Soft Deletion and new APIs
1. given an active score object
course = Course.create!
user = User.create!
enrollment = StudentEnrollment.create!(course: course, user: user)
score = enrollment.scores.create!
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
2. When destroying a score
score.destroy
3. Then metadata is soft-deleted
metadata.reload.deleted? # => true
4. When undestroying score
score.undestroy
5. Then metadata is also active
metadata.reload.active? # => true
6. When destroying a metadata
metadata.destroy
7. Then metadata is soft-deleted
metadata.deleted? # => true
8. When undestroying metadata
metadata.undestroy
9. Then metadata is active
metadata.active? # => true
10. When permanently destroying a metadata
metadata.destroy_permanently!
11. Then metadata is for real dog gone
metadata.destroyed? # => true
12. Given a score with a metadata
metadata = score.create_score_metadata!(
calculation_details: {foo: :bar}
)
13. When permanently destroying a score
score.destroy_permanently!
14. Then metadata is for real dog gone
metadata.destroyed? # => true
15. Given a score with no associated metadata
score = enrollment.scores.create!
16. When destroying a score
score.destroy
17. Then the score is soft-deleted
score.deleted? # => true
18. When undestroying a score
score.undestroy
19. Then the score is active
score.active? # => true
20. When permanently destroying a score
score.destroy_permanently!
21. Then score is for real dog destroyed
score.destroyed? # => true
Change-Id: I251c621c679ae9f3b4e0784367e596c28266faaf
Reviewed-on: https://gerrit.instructure.com/139061
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-01-25 08:38:25 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#undestroy" do
|
|
|
|
context "without score metadata" do
|
|
|
|
it "is active" do
|
|
|
|
score.destroy
|
|
|
|
score.undestroy
|
|
|
|
expect(score).to be_active
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with score metadata" do
|
|
|
|
let(:metadata) { score.create_score_metadata!(calculation_details: { foo: :bar }) }
|
|
|
|
|
|
|
|
describe "score_metadata association" do
|
|
|
|
it "is active" do
|
|
|
|
metadata.score.destroy
|
|
|
|
metadata.score.undestroy
|
|
|
|
expect(metadata).to be_active
|
|
|
|
end
|
|
|
|
end
|
2017-10-05 02:34:31 +08:00
|
|
|
end
|
2016-07-20 01:31:02 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "#current_grade" do
|
|
|
|
it "delegates the grade conversion to the course" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:score_to_grade).once.with(score.current_score)
|
2016-07-20 01:31:02 +08:00
|
|
|
score.current_grade
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns nil if grading schemes are not used in the course" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:grading_standard_enabled?).and_return(false)
|
2016-07-20 01:31:02 +08:00
|
|
|
expect(score.current_grade).to be_nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the grade according to the course grading scheme" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:grading_standard_enabled?).and_return(true)
|
2016-07-20 01:31:02 +08:00
|
|
|
expect(score.current_grade).to eq "B-"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#final_grade" do
|
|
|
|
it "delegates the grade conversion to the course" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:score_to_grade).once.with(score.final_score)
|
2016-07-20 01:31:02 +08:00
|
|
|
score.final_grade
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns nil if grading schemes are not used in the course" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:grading_standard_enabled?).and_return(false)
|
2016-07-20 01:31:02 +08:00
|
|
|
expect(score.final_grade).to be_nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the grade according to the course grading scheme" do
|
2017-07-27 23:41:07 +08:00
|
|
|
expect(score.course).to receive(:grading_standard_enabled?).and_return(true)
|
2016-07-20 01:31:02 +08:00
|
|
|
expect(score.final_grade).to eq "C"
|
|
|
|
end
|
|
|
|
end
|
2017-07-21 05:46:10 +08:00
|
|
|
|
2017-10-14 00:56:35 +08:00
|
|
|
describe("#scorable") do
|
2017-08-17 21:47:36 +08:00
|
|
|
it "returns course for course score" do
|
|
|
|
expect(score.scorable).to be score.enrollment.course
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns grading period for grading period score" do
|
|
|
|
expect(grading_period_score.scorable).to be grading_period_score.grading_period
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns assignment group for assignment group score" do
|
|
|
|
expect(assignment_group_score.scorable).to be assignment_group_score.assignment_group
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-14 00:56:35 +08:00
|
|
|
describe("#course_score") do
|
2017-08-17 21:47:36 +08:00
|
|
|
it "sets course_score to true when there are no scorable associations" do
|
|
|
|
expect(score.course_score).to be true
|
|
|
|
end
|
|
|
|
|
|
|
|
it "sets course_score to false for grading period scores" do
|
|
|
|
expect(grading_period_score.course_score).to be false
|
|
|
|
end
|
|
|
|
|
|
|
|
it "sets course_score to false for assignment group scores" do
|
|
|
|
expect(assignment_group_score.course_score).to be false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe("#params_for_course") do
|
2017-10-14 00:56:35 +08:00
|
|
|
it("uses course_score") do
|
2017-08-17 21:47:36 +08:00
|
|
|
expect(Score.params_for_course).to eq(course_score: true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-21 05:46:10 +08:00
|
|
|
context "permissions" do
|
|
|
|
it "allows the proper people" do
|
2017-08-17 21:47:36 +08:00
|
|
|
expect(score.grants_right?(@enrollment.user, :read)).to be true
|
2017-07-21 05:46:10 +08:00
|
|
|
|
|
|
|
teacher_in_course(active_all: true)
|
2017-08-17 21:47:36 +08:00
|
|
|
expect(score.grants_right?(@teacher, :read)).to be true
|
2017-07-21 05:46:10 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't work for nobody" do
|
2017-08-17 21:47:36 +08:00
|
|
|
expect(score.grants_right?(nil, :read)).to be false
|
2017-07-21 05:46:10 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't allow random classmates to read" do
|
|
|
|
score
|
|
|
|
student_in_course(active_all: true)
|
|
|
|
expect(score.grants_right?(@student, :read)).to be false
|
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't work for yourself if the course is configured badly" do
|
|
|
|
@enrollment.course.hide_final_grade = true
|
|
|
|
@enrollment.course.save!
|
|
|
|
expect(score.grants_right?(@enrollment.user, :read)).to be false
|
|
|
|
end
|
|
|
|
end
|
2018-10-25 00:39:20 +08:00
|
|
|
|
|
|
|
describe "final grade override" do
|
|
|
|
describe "#effective_final_score" do
|
|
|
|
it "returns the override score when one is present" do
|
|
|
|
score.update!(override_score: 88)
|
|
|
|
expect(score.effective_final_score).to eq 88
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the calculated final score when no override is present" do
|
|
|
|
expect(score.effective_final_score).to eq 74
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#effective_final_grade" do
|
|
|
|
it "returns a grade commensurate with the override score when one is present" do
|
|
|
|
score.update!(override_score: 88)
|
|
|
|
allow(score.course).to receive(:grading_standard_enabled?).and_return(true)
|
|
|
|
expect(score.effective_final_grade).to eq "B+"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the calculated final grade when no override score is present" do
|
|
|
|
allow(score.course).to receive(:grading_standard_enabled?).and_return(true)
|
|
|
|
expect(score.effective_final_grade).to eq "C"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-07-20 01:31:02 +08:00
|
|
|
end
|