Update CreateDiscussionTopic to support checkpoints

refs VICE-4020
flag=discussion_checkpoints

test plan:
  - Specs pass.
  - Create a graded discussion topic with
      checkpoints using this mutation:
mutation MyMutation {
  createDiscussionTopic(
    input: {
      contextId: "1"
      contextType: Course
      title: "Checkpoints Test"
      assignment: { courseId: "1", name: "Test", forCheckpoints: true }
      checkpoints: [
        {
          checkpointLabel: "reply_to_topic",
          pointsPossible: 10,
          dates: [{ type: everyone, dueAt: "2016-07-10T18:00:00-01:00" }]
        },
        {
          checkpointLabel: "reply_to_entry",
          pointsPossible: 10,
          dates: [{ type: everyone, dueAt: "2016-07-15T18:00:00-01:00" }],
          repliesRequired: 3
        }
      ]
    }
  ) {
    discussionTopic {
      _id
    }
    errors {
      attribute
      message
    }
  }
}

qa risk: low

Change-Id: I750c26a5eda04eb98bdd1b7864415ef5d9c4dbab
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/337380
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jason Gillett <jason.gillett@instructure.com>
Reviewed-by: Spencer Olson <solson@instructure.com>
QA-Review: Jason Gillett <jason.gillett@instructure.com>
Product-Review: Omar Soto-Fortuño <omar.soto@instructure.com>
This commit is contained in:
Omar Gerardo Soto-Fortuño 2024-01-12 11:45:04 -05:00 committed by Omar Soto-Fortuño
parent ea83d570fe
commit f77772dedb
17 changed files with 380 additions and 31 deletions

View File

@ -63,6 +63,7 @@ class Mutations::AssignmentInputBase < GraphQL::Schema::InputObject
argument :points_possible, Float, required: false
argument :post_to_sis, Boolean, required: false
argument :unlock_at, Types::DateTimeType, required: false
argument :for_checkpoints, Boolean, required: false
end
class Mutations::AssignmentCreate < Mutations::AssignmentInputBase

View File

@ -42,6 +42,7 @@ class Mutations::CreateDiscussionTopic < Mutations::DiscussionBase
argument :context_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("Context")
argument :context_type, Types::DiscussionTopicContextType, required: true
argument :assignment, Mutations::AssignmentCreate, required: false
argument :checkpoints, [Mutations::DiscussionCheckpoints], required: false
# most arguments inherited from DiscussionBase
@ -122,12 +123,32 @@ class Mutations::CreateDiscussionTopic < Mutations::DiscussionBase
elsif working_assignment.present?
discussion_topic.assignment = working_assignment&.[](:assignment)
end
# Assignment must be present to set checkpoints
if input[:checkpoints]&.count == DiscussionTopic::REQUIRED_CHECKPOINT_COUNT
return validation_error(I18n.t("If checkpoints are defined, forCheckpoints: true must be provided to the discussion topic assignment.")) unless input.dig(:assignment, :for_checkpoints)
input[:checkpoints].each do |checkpoint|
dates = checkpoint[:dates]&.map(&:to_object)
Checkpoints::DiscussionCheckpointCreatorService.call(
discussion_topic:,
checkpoint_label: checkpoint[:checkpoint_label],
points_possible: checkpoint[:points_possible],
dates:
)
end
end
end
discussion_topic.saved_by = :assignment if discussion_topic.assignment.present?
return errors_for(discussion_topic) unless discussion_topic.save!
{ discussion_topic: }
rescue Checkpoints::DiscussionCheckpointError => e
raise GraphQL::ExecutionError, e.message
rescue ActiveRecord::RecordInvalid
errors_for(discussion_topic)
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "Not found"
end

View File

@ -18,6 +18,46 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class Types::DiscussionCheckpointDateType < Types::BaseEnum
graphql_name "DiscussionCheckpointDateType"
description "Types of dates that can be set for discussion checkpoints"
value "everyone"
value "override"
end
class Types::DiscussionCheckpointDateSetType < Types::BaseEnum
graphql_name "DiscussionCheckpointDateSetType"
description "Types of date set that can be set for discussion checkpoints"
value "CourseSection"
value "Group"
value "ADHOC"
end
class Mutations::DiscussionCheckpointDate < GraphQL::Schema::InputObject
argument :type, Types::DiscussionCheckpointDateType, required: true
argument :due_at, Types::DateTimeType, required: true
argument :student_ids, [Integer], required: false
argument :set_type, Types::DiscussionCheckpointDateSetType, required: false
argument :set_id, Integer, required: false
def to_object
{
type: self[:type],
due_at: self[:due_at],
student_ids: self[:student_ids],
set_type: self[:set_type],
set_id: self[:set_id]
}
end
end
class Mutations::DiscussionCheckpoints < GraphQL::Schema::InputObject
argument :checkpoint_label, String, required: true
argument :dates, [Mutations::DiscussionCheckpointDate], required: true
argument :points_possible, Integer, required: true
argument :replies_required, Integer, required: false
end
class Mutations::DiscussionBase < Mutations::BaseMutation
argument :allow_rating, Boolean, required: false
argument :delayed_post_at, Types::DateTimeType, required: false

View File

@ -34,6 +34,8 @@ class DiscussionTopic < ActiveRecord::Base
include DuplicatingObjects
include LockedFor
REQUIRED_CHECKPOINT_COUNT = 2
restrict_columns :content, [:title, :message]
restrict_columns :settings, %i[require_initial_post
discussion_type

View File

@ -18,10 +18,9 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
class Checkpoints::AdhocOverrideCreatorService < ApplicationService
require_relative "discussion_checkpoint_error"
include Checkpoints::DateOverrider
class StudentIdsRequiredError < StandardError; end
def initialize(checkpoint:, override:)
super()
@checkpoint = checkpoint
@ -29,7 +28,9 @@ class Checkpoints::AdhocOverrideCreatorService < ApplicationService
end
def call
desired_student_ids = @override.fetch(:student_ids) { raise StudentIdsRequiredError, "student_ids is required, but was not provided" }
desired_student_ids = @override.fetch(:student_ids) { raise Checkpoints::StudentIdsRequiredError, "student_ids is required, but was not provided" }
raise Checkpoints::StudentIdsRequiredError, "student_ids is required, but was not provided" if desired_student_ids.blank?
student_ids = @checkpoint.course.all_students.where(id: desired_student_ids).pluck(:id)
override = build_override(assignment: @checkpoint, student_ids:)
build_override_students(override:, student_ids:)

View File

@ -18,9 +18,6 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
class Checkpoints::DateOverrideCreatorService < ApplicationService
class SetTypeRequiredError < StandardError; end
class SetTypeNotSupportedError < StandardError; end
def initialize(checkpoint:, overrides:)
super()
@checkpoint = checkpoint
@ -29,8 +26,8 @@ class Checkpoints::DateOverrideCreatorService < ApplicationService
def call
@overrides.each do |override|
set_type = override.fetch(:set_type) { raise SetTypeRequiredError, "set_type is required, but was not provided" }
service = services.fetch(set_type) { |key| raise SetTypeNotSupportedError, "set_type of '#{key}' not supported. Supported types: #{services.keys}" }
set_type = override.fetch(:set_type) { raise Checkpoints::SetTypeRequiredError, "set_type is required, but was not provided" }
service = services.fetch(set_type) { |key| raise Checkpoints::SetTypeNotSupportedError, "set_type of '#{key}' not supported. Supported types: #{services.keys}" }
service.call(checkpoint: @checkpoint, override:)
end
end

View File

@ -18,8 +18,7 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
class Checkpoints::DiscussionCheckpointCreatorService < ApplicationService
class FlagDisabledError < StandardError; end
class DateTypeRequiredError < StandardError; end
require_relative "discussion_checkpoint_error"
def initialize(discussion_topic:, checkpoint_label:, dates:, points_possible:, replies_required: 1)
super()
@ -32,8 +31,19 @@ class Checkpoints::DiscussionCheckpointCreatorService < ApplicationService
end
def call
unless @discussion_topic.root_account.feature_enabled?(:discussion_checkpoints)
raise FlagDisabledError, "discussion_checkpoints feature flag must be enabled"
unless @discussion_topic.context.root_account.feature_enabled?(:discussion_checkpoints)
raise Checkpoints::FlagDisabledError, "discussion_checkpoints feature flag must be enabled"
end
valid_date_types = %w[everyone override].freeze
@dates.each do |date|
if date[:type].blank?
raise Checkpoints::DateTypeRequiredError, "each date must have a type specified ('everyone' or 'override')"
end
unless valid_date_types.include?(date[:type])
raise Checkpoints::InvalidDateTypeError, "invalid date type: #{date[:type]}"
end
end
checkpoint = create_checkpoint
@ -127,7 +137,7 @@ class Checkpoints::DiscussionCheckpointCreatorService < ApplicationService
def dates_by_type(type)
@dates.select do |date|
date_type = date.fetch(:type) { raise DateTypeRequiredError, "each date must have a type specified ('everyone' or 'override')" }
date_type = date.fetch(:type) { raise Checkpoints::DateTypeRequiredError, "each date must have a type specified ('everyone' or 'override')" }
date_type == type
end
end

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
#
# Copyright (C) 2024 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
module Checkpoints
class DiscussionCheckpointError < StandardError; end
class FlagDisabledError < DiscussionCheckpointError; end
class DateTypeRequiredError < DiscussionCheckpointError; end
class InvalidDateTypeError < DiscussionCheckpointError; end
class SetTypeRequiredError < DiscussionCheckpointError; end
class SetTypeNotSupportedError < DiscussionCheckpointError; end
class GroupAssignmentRequiredError < DiscussionCheckpointError; end
class SetIdRequiredError < DiscussionCheckpointError; end
class StudentIdsRequiredError < DiscussionCheckpointError; end
end

View File

@ -18,11 +18,9 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
class Checkpoints::GroupOverrideCreatorService < ApplicationService
require_relative "discussion_checkpoint_error"
include Checkpoints::DateOverrider
class GroupAssignmentRequiredError < StandardError; end
class SetIdRequiredError < StandardError; end
def initialize(checkpoint:, override:)
super()
@checkpoint = checkpoint
@ -31,10 +29,10 @@ class Checkpoints::GroupOverrideCreatorService < ApplicationService
def call
if @checkpoint.effective_group_category_id.nil?
raise GroupAssignmentRequiredError, "must be a group assignment in order to create group overrides"
raise Checkpoints::GroupAssignmentRequiredError, "must be a group assignment in order to create group overrides"
end
group_id = @override.fetch(:set_id) { raise SetIdRequiredError, "set_id is required, but was not provided" }
group_id = @override.fetch(:set_id) { raise Checkpoints::SetIdRequiredError, "set_id is required, but was not provided" }
group = @checkpoint.course.active_groups.where(group_category_id: @checkpoint.effective_group_category_id).find(group_id)
override = create_override(assignment: @checkpoint, group:)

View File

@ -20,8 +20,6 @@
class Checkpoints::SectionOverrideCreatorService < ApplicationService
include Checkpoints::DateOverrider
class SetIdRequiredError < StandardError; end
def initialize(checkpoint:, override:)
super()
@checkpoint = checkpoint
@ -29,7 +27,9 @@ class Checkpoints::SectionOverrideCreatorService < ApplicationService
end
def call
section_id = @override.fetch(:set_id) { raise SetIdRequiredError, "set_id is required, but was not provided" }
section_id = @override.fetch(:set_id) { raise Checkpoints::SetIdRequiredError, "set_id is required, but was not provided" }
raise Checkpoints::SetIdRequiredError, "set_id is required, but was not provided" if section_id.blank?
section = @checkpoint.course.active_course_sections.find(section_id)
override = create_override(assignment: @checkpoint, section:)

View File

@ -1061,4 +1061,245 @@ describe Mutations::CreateDiscussionTopic do
expect(result["data"]["createDiscussionTopic"]["errors"][0]["message"]).to eq "[[:base, \"unknown student ids: [\\\"#{@teacher.id - 1}\\\"]\"]]"
end
end
context "checkpoints" do
before(:once) do
@course.root_account.enable_feature!(:discussion_checkpoints)
end
it "successfully creates a discussion topic with checkpoints" do
context_type = "Course"
title = "Graded Discussion w/Checkpoints"
message = "Lorem ipsum..."
published = true
query = <<~GQL
contextId: "#{@course.id}"
contextType: #{context_type}
title: "#{title}"
message: "#{message}"
published: #{published}
assignment: {
courseId: "#{@course.id}",
name: "#{title}",
forCheckpoints: true
}
checkpoints: [
{
checkpointLabel: "reply_to_topic",
pointsPossible: 10,
dates: [{ type: everyone, dueAt: "#{5.days.from_now.iso8601}" }]
},
{
checkpointLabel: "reply_to_entry",
pointsPossible: 15,
dates: [{ type: everyone, dueAt: "#{10.days.from_now.iso8601}" }],
repliesRequired: 3
}
]
GQL
result = execute_with_input_with_assignment(query)
expect(result["errors"]).to be_nil
end
it "successfully creates a discussion topic with checkpoints and CourseSection overrides" do
section1 = add_section("M03")
section2 = add_section("M06")
context_type = "Course"
title = "Graded Discussion w/Checkpoints and CourseSection overrides"
message = "Lorem ipsum..."
published = true
reply_to_entry_due_at1 = 12.days.from_now
reply_to_entry_due_at2 = 14.days.from_now
query = <<~GQL
contextId: "#{@course.id}"
contextType: #{context_type}
title: "#{title}"
message: "#{message}"
published: #{published}
assignment: {
courseId: "#{@course.id}",
name: "#{title}",
forCheckpoints: true
}
checkpoints: [
{
checkpointLabel: "reply_to_topic",
pointsPossible: 10,
dates: [{ type: everyone, dueAt: "#{5.days.from_now.iso8601}" }]
},
{
checkpointLabel: "reply_to_entry",
pointsPossible: 15,
dates: [
{ type: everyone, dueAt: "#{10.days.from_now.iso8601}" },
{ type: override, dueAt: "#{reply_to_entry_due_at1.iso8601}", setType: CourseSection, setId: #{section1.id} },
{ type: override, dueAt: "#{reply_to_entry_due_at2.iso8601}", setType: CourseSection, setId: #{section2.id} }
],
repliesRequired: 3
}
]
GQL
result = execute_with_input_with_assignment(query)
expect(result["errors"]).to be_nil
assignment = Assignment.last
expect(assignment.has_sub_assignments?).to be true
sub_assignments = SubAssignment.where(parent_assignment_id: assignment.id)
sub_assignment1 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_TOPIC)
sub_assignment2 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_ENTRY)
expect(sub_assignment1.sub_assignment_tag).to eq "reply_to_topic"
expect(sub_assignment1.points_possible).to eq 10
expect(sub_assignment2.sub_assignment_tag).to eq "reply_to_entry"
expect(sub_assignment2.points_possible).to eq 15
assignment_override1 = AssignmentOverride.find_by(assignment: sub_assignment2, set_type: "CourseSection", set_id: section1.id)
assignment_override2 = AssignmentOverride.find_by(assignment: sub_assignment2, set_type: "CourseSection", set_id: section2.id)
expect(assignment_override1).to be_present
expect(assignment_override2).to be_present
expect(assignment_override1.due_at).to be_within(1.second).of reply_to_entry_due_at1
expect(assignment_override2.due_at).to be_within(1.second).of reply_to_entry_due_at2
end
it "successfully creates a discussion topic with checkpoints and Group overrides" do
group = @course.groups.create!
student_in_group = student_in_course(course: @course, active_all: true).user
group.group_memberships.create!(user: student_in_group)
context_type = "Course"
title = "Graded Discussion w/Checkpoints and Group overrides"
message = "Lorem ipsum..."
published = true
reply_to_entry_due_at = 12.days.from_now
query = <<~GQL
contextId: "#{@course.id}"
contextType: #{context_type}
title: "#{title}"
message: "#{message}"
published: #{published}
groupCategoryId: #{group.group_category.id}
assignment: {
courseId: "#{@course.id}",
name: "#{title}",
forCheckpoints: true
}
checkpoints: [
{
checkpointLabel: "reply_to_topic",
pointsPossible: 10,
dates: [{ type: everyone, dueAt: "#{5.days.from_now.iso8601}" }]
},
{
checkpointLabel: "reply_to_entry",
pointsPossible: 15,
dates: [
{ type: everyone, dueAt: "#{10.days.from_now.iso8601}" },
{ type: override, dueAt: "#{reply_to_entry_due_at.iso8601}", setType: Group, setId: #{group.id} }
],
repliesRequired: 3
}
]
GQL
result = execute_with_input_with_assignment(query)
expect(result["errors"]).to be_nil
assignment = Assignment.last
expect(assignment.has_sub_assignments?).to be true
sub_assignments = SubAssignment.where(parent_assignment_id: assignment.id)
sub_assignment1 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_TOPIC)
sub_assignment2 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_ENTRY)
expect(sub_assignment1.sub_assignment_tag).to eq "reply_to_topic"
expect(sub_assignment1.points_possible).to eq 10
expect(sub_assignment2.sub_assignment_tag).to eq "reply_to_entry"
expect(sub_assignment2.points_possible).to eq 15
assignment_override = AssignmentOverride.find_by(assignment: sub_assignment2, set_type: "Group", set_id: group.id)
expect(assignment_override).to be_present
expect(assignment_override.due_at).to be_within(1.second).of reply_to_entry_due_at
end
it "successfully creates a discussion topic with checkpoints and AdHoc overrides" do
student1 = student_in_course(course: @course, active_all: true).user
student2 = student_in_course(course: @course, active_all: true).user
context_type = "Course"
title = "Graded Discussion w/Checkpoints and AdHoc overrides"
message = "Lorem ipsum..."
published = true
reply_to_entry_due_at = 12.days.from_now
query = <<~GQL
contextId: "#{@course.id}"
contextType: #{context_type}
title: "#{title}"
message: "#{message}"
published: #{published}
assignment: {
courseId: "#{@course.id}",
name: "#{title}",
forCheckpoints: true
}
checkpoints: [
{
checkpointLabel: "reply_to_topic",
pointsPossible: 10,
dates: [{ type: everyone, dueAt: "#{5.days.from_now.iso8601}" }]
},
{
checkpointLabel: "reply_to_entry",
pointsPossible: 15,
dates: [
{ type: everyone, dueAt: "#{10.days.from_now.iso8601}" },
{ type: override, dueAt: "#{reply_to_entry_due_at.iso8601}", setType: ADHOC, studentIds: [#{student1.id}, #{student2.id}] }
],
repliesRequired: 3
}
]
GQL
result = execute_with_input_with_assignment(query)
expect(result["errors"]).to be_nil
assignment = Assignment.last
expect(assignment.has_sub_assignments?).to be true
sub_assignments = SubAssignment.where(parent_assignment_id: assignment.id)
sub_assignment1 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_TOPIC)
sub_assignment2 = sub_assignments.find_by(sub_assignment_tag: CheckpointLabels::REPLY_TO_ENTRY)
expect(sub_assignment1.sub_assignment_tag).to eq "reply_to_topic"
expect(sub_assignment1.points_possible).to eq 10
expect(sub_assignment2.sub_assignment_tag).to eq "reply_to_entry"
expect(sub_assignment2.points_possible).to eq 15
assignment_override = AssignmentOverride.find_by(assignment: sub_assignment2)
expect(assignment_override).to be_present
expect(assignment_override.set_type).to eq "ADHOC"
expect(assignment_override.due_at).to be_within(1.second).of reply_to_entry_due_at
student_ids = assignment_override.assignment_override_students.pluck(:user_id)
expect(student_ids).to match_array [student1.id, student2.id]
end
end
end

View File

@ -3004,8 +3004,8 @@ describe DiscussionTopic do
describe "checkpoints" do
before do
@course.root_account.enable_feature!(:discussion_checkpoints)
@topic = DiscussionTopic.create_graded_topic!(course: @course, title: "Discussion Topic Title", user: @teacher)
@topic.root_account.enable_feature!(:discussion_checkpoints)
end
it "not in place in the topic" do

View File

@ -35,7 +35,7 @@ describe Checkpoints::AdhocOverrideCreatorService do
override = { due_at: 2.days.from_now }
expect do
service.call(checkpoint: @checkpoint, override:)
end.to raise_error(Checkpoints::AdhocOverrideCreatorService::StudentIdsRequiredError)
end.to raise_error(Checkpoints::StudentIdsRequiredError)
end
it "creates a parent adhoc override without dates set (but still overridden), if one doesn't already exist" do

View File

@ -33,14 +33,14 @@ describe Checkpoints::DateOverrideCreatorService do
overrides = [{ type: "override", due_at: 2.days.from_now }]
expect do
service.call(checkpoint: @checkpoint, overrides:)
end.to raise_error(Checkpoints::DateOverrideCreatorService::SetTypeRequiredError)
end.to raise_error(Checkpoints::SetTypeRequiredError)
end
it "raises a SetTypeNotSupportedError when a provided date has an unsupported set_type" do
overrides = [{ type: "override", set_type: "Potato", due_at: 2.days.from_now }]
expect do
service.call(checkpoint: @checkpoint, overrides:)
end.to raise_error(Checkpoints::DateOverrideCreatorService::SetTypeNotSupportedError)
end.to raise_error(Checkpoints::SetTypeNotSupportedError)
end
it "calls the SectionOverrideCreatorService to create a section override" do

View File

@ -28,7 +28,7 @@ describe Checkpoints::DiscussionCheckpointCreatorService do
let(:service) { Checkpoints::DiscussionCheckpointCreatorService }
it "raises a FlagDisabledError when the checkpoints feature flag is disabled" do
@topic.root_account.disable_feature!(:discussion_checkpoints)
@topic.context.root_account.disable_feature!(:discussion_checkpoints)
expect do
service.call(
@ -37,7 +37,7 @@ describe Checkpoints::DiscussionCheckpointCreatorService do
dates: [{ type: "everyone", due_at: 2.days.from_now }],
points_possible: 6
)
end.to raise_error(Checkpoints::DiscussionCheckpointCreatorService::FlagDisabledError)
end.to raise_error(Checkpoints::FlagDisabledError)
end
it "raises a DateTypeRequiredError when a type is not specified on a date" do
@ -48,7 +48,7 @@ describe Checkpoints::DiscussionCheckpointCreatorService do
dates: [{ due_at: 2.days.from_now }],
points_possible: 6
)
end.to raise_error(Checkpoints::DiscussionCheckpointCreatorService::DateTypeRequiredError)
end.to raise_error(Checkpoints::DateTypeRequiredError)
end
it "updates the reply_to_entry_required_count on the topic when creating a reply to entry checkpoint" do

View File

@ -36,14 +36,14 @@ describe Checkpoints::GroupOverrideCreatorService do
override = { set_id: @group.id, due_at: 2.days.from_now }
expect do
service.call(checkpoint: @checkpoint, override:)
end.to raise_error(Checkpoints::GroupOverrideCreatorService::GroupAssignmentRequiredError)
end.to raise_error(Checkpoints::GroupAssignmentRequiredError)
end
it "raises an error if set_id is not provided" do
override = { due_at: 2.days.from_now }
expect do
service.call(checkpoint: @checkpoint, override:)
end.to raise_error(Checkpoints::GroupOverrideCreatorService::SetIdRequiredError)
end.to raise_error(Checkpoints::SetIdRequiredError)
end
it "raises an error if provided a set_id for a soft-deleted group" do

View File

@ -34,7 +34,7 @@ describe Checkpoints::SectionOverrideCreatorService do
override = { due_at: 2.days.from_now }
expect do
service.call(checkpoint: @checkpoint, override:)
end.to raise_error(Checkpoints::SectionOverrideCreatorService::SetIdRequiredError)
end.to raise_error(Checkpoints::SetIdRequiredError)
end
it "raises an error if provided a set_id for a soft-deleted section" do