diff --git a/app/api/entities/feedback_entities/feedback_comment_entity.rb b/app/api/entities/feedback_entities/feedback_comment_entity.rb new file mode 100644 index 000000000..6975f49bf --- /dev/null +++ b/app/api/entities/feedback_entities/feedback_comment_entity.rb @@ -0,0 +1,6 @@ +module Entities + class FeedbackCommentEntity < Grape::Entity + expose :id + expose :comment + end +end diff --git a/app/api/entities/feedback_entities/feedback_comment_template_entity.rb b/app/api/entities/feedback_entities/feedback_comment_template_entity.rb new file mode 100644 index 000000000..7a2b01933 --- /dev/null +++ b/app/api/entities/feedback_entities/feedback_comment_template_entity.rb @@ -0,0 +1,7 @@ +module Entities + class FeedbackCommentTemplateEntity < Grape::Entity + expose :id + expose :comment_text_situation + expose :comment_text_next_action + end +end diff --git a/app/models/feedback/criterion.rb b/app/models/feedback/criterion.rb index 24e8b9d6b..cc06b0948 100644 --- a/app/models/feedback/criterion.rb +++ b/app/models/feedback/criterion.rb @@ -4,7 +4,7 @@ class Criterion < ApplicationRecord has_many :criterion_options, dependent: :destroy # Constraints - # validates_associated :stage + validates_associated :stage validates :order, :description, presence: true validates :order, numericality: { greater_than_or_equal_to: 0, only_integer: true, diff --git a/app/models/feedback/criterion_option.rb b/app/models/feedback/criterion_option.rb index 45b406342..a6c05bd58 100644 --- a/app/models/feedback/criterion_option.rb +++ b/app/models/feedback/criterion_option.rb @@ -4,4 +4,7 @@ class CriterionOption < ApplicationRecord belongs_to :task_status has_many :feedback_comment_templates has_many :feedback_comments + + # Constraints + validates_associated :criterion end diff --git a/app/models/feedback/feedback_comment.rb b/app/models/feedback/feedback_comment.rb index b3e31372e..6fcbb5d0d 100644 --- a/app/models/feedback/feedback_comment.rb +++ b/app/models/feedback/feedback_comment.rb @@ -3,5 +3,5 @@ class FeedbackComment < TaskComment belongs_to :criterion_option # Constraints - validates :comment_text, presence: true + validates :comment, presence: true end diff --git a/app/models/feedback/feedback_comment_template.rb b/app/models/feedback/feedback_comment_template.rb index 2acaab01a..a43fc18fb 100644 --- a/app/models/feedback/feedback_comment_template.rb +++ b/app/models/feedback/feedback_comment_template.rb @@ -1,6 +1,5 @@ class FeedbackCommentTemplate < ApplicationRecord # Associations - # belongs_to :stage -- other direction belongs_to :criterion_option # Constraints diff --git a/app/models/feedback/stage.rb b/app/models/feedback/stage.rb index 5cc0c137f..08582dbef 100644 --- a/app/models/feedback/stage.rb +++ b/app/models/feedback/stage.rb @@ -2,7 +2,6 @@ class Stage < ApplicationRecord # Associations belongs_to :task_definition has_many :criteria, dependent: :destroy - has_many :feedback_comment_templates has_one :unit, through: :task_definition # Constraints diff --git a/app/models/task_status.rb b/app/models/task_status.rb index 825fc5c25..1c99c1537 100644 --- a/app/models/task_status.rb +++ b/app/models/task_status.rb @@ -6,6 +6,7 @@ class TaskStatus < ApplicationRecord # Model associations has_many :tasks + has_many :criterion_options # # Override find to ensure that task status objects are cached - these do not change diff --git a/db/migrate/20221215042412_add_tables_for_feedback_enhancement.rb b/db/migrate/20221215042412_add_tables_for_feedback_enhancement.rb index 00c6288a0..5d92141ad 100644 --- a/db/migrate/20221215042412_add_tables_for_feedback_enhancement.rb +++ b/db/migrate/20221215042412_add_tables_for_feedback_enhancement.rb @@ -11,7 +11,6 @@ def change # Foreign keys t.references :task_definition - t.references :feedback_comment_template end create_table :criteria do |t| # "criteria" is set as plural of "criterion" in 'doubtfire-api/config/initializers/inflections.rb' diff --git a/db/schema.rb b/db/schema.rb index ed7cb1164..720dddfac 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -229,8 +229,6 @@ t.string "exit_message_good" t.string "exit_message_resubmit" t.bigint "task_definition_id" - t.bigint "feedback_comment_template_id" - t.index ["feedback_comment_template_id"], name: "index_stages_on_feedback_comment_template_id" t.index ["task_definition_id"], name: "index_stages_on_task_definition_id" end diff --git a/test/factories/feedback/criterion_factory.rb b/test/factories/feedback/criterion_factory.rb new file mode 100644 index 000000000..d68ed1668 --- /dev/null +++ b/test/factories/feedback/criterion_factory.rb @@ -0,0 +1,18 @@ + +FactoryBot.define do + factory :criterion do + transient do + number_of_criterion_options {0} + end + + stage + + sequence(:order) { |n| n } + description { Faker::Lorem.sentence } + help_text { Faker::Lorem.sentence } + + after(:create) do |criterion, evaluator| + create_list(:criterion_option, evaluator.number_of_criterion_options, criterion: criterion) + end + end +end diff --git a/test/factories/feedback/criterion_option_factory.rb b/test/factories/feedback/criterion_option_factory.rb new file mode 100644 index 000000000..952e05bb7 --- /dev/null +++ b/test/factories/feedback/criterion_option_factory.rb @@ -0,0 +1,19 @@ + +FactoryBot.define do + factory :criterion_option do + transient do + number_of_feedback_comment_templates {0} + end + + association :criterion # associates according to relationship within models + task_status { TaskStatus.all.sample } + + # outcome_status + resolved_message_text { Faker::Lorem.sentence } + unresolved_message_text { Faker::Lorem.sentence } + + after(:create) do |criterion_option, evaluator| + create_list(:feedback_comment_template, evaluator.number_of_feedback_comment_templates, criterion_option: criterion_option) + end + end +end diff --git a/test/factories/feedback/feedback_comment_factory.rb b/test/factories/feedback/feedback_comment_factory.rb new file mode 100644 index 000000000..df4963f37 --- /dev/null +++ b/test/factories/feedback/feedback_comment_factory.rb @@ -0,0 +1,8 @@ + +FactoryBot.define do + factory :feedback_comment do + + association :feedback_comment_template + association :criterion_option + end +end diff --git a/test/factories/feedback/feedback_comment_template_factory.rb b/test/factories/feedback/feedback_comment_template_factory.rb new file mode 100644 index 000000000..7f4a98564 --- /dev/null +++ b/test/factories/feedback/feedback_comment_template_factory.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :feedback_comment_template do + criterion_option + + comment_text_situation { Faker::Lorem.sentence } + comment_text_next_action { Faker::Lorem.sentence } + end +end diff --git a/test/factories/feedback/stage_factory.rb b/test/factories/feedback/stage_factory.rb index 015e33da9..7d74fcc0f 100644 --- a/test/factories/feedback/stage_factory.rb +++ b/test/factories/feedback/stage_factory.rb @@ -1,24 +1,25 @@ # Read about factories at https://github.com/thoughtbot/factory_bot FactoryBot.define do + factory :stage do - transient do - number_of_criterion {0} - end - task_definition + association :task_definition + + transient do # transient: not persisted to database + number_of_criterion {0} # `0` criteria created unless otherwise specified + # E.g., "FactoryBot.create(:stage, number_of_criterion: 3)" + end sequence(:order) { |n| n } sequence(:title) { |n| "Stage-#{n}" } - help_text { Faker::Lorem.sentence } entry_message { Faker::Lorem.sentence } exit_message_good { Faker::Lorem.sentence } exit_message_resubmit { Faker::Lorem.sentence } - after(:build) do |stage, eval| - # Create a list of criterion that refer to the created stage - create_list(:criteria, eval.number_of_criterion, stage: stage) + after(:create) do |stage, evaluator| + create_list(:criteria, evaluator.number_of_criterion, stage: stage) end end end diff --git a/test/models/feedback/criterion_model_test.rb b/test/models/feedback/criterion_model_test.rb index 5c1b0f0de..5203550ab 100644 --- a/test/models/feedback/criterion_model_test.rb +++ b/test/models/feedback/criterion_model_test.rb @@ -4,15 +4,15 @@ # Tests for Criterion model objects - not accessed via API # class CriterionModelTest < ActiveSupport::TestCase - def app - Rails.application + + setup do + DatabaseCleaner.start + @stage = FactoryBot.create(:stage) end # Test you can create a valid criterion - def test_criterion_creation - td = FactoryBot.create(:task_definition) - stage = Stage.create(task_definition: td, title: 'Stage 1', order: 1) - criterion = Criterion.create(stage: stage, description: 'Criterion 1', order: 1) + def test_valid_criterion_creation + criterion = Criterion.create(stage: @stage, description: 'Criterion 1', order: 1) assert criterion assert criterion.stage @@ -22,17 +22,20 @@ def test_criterion_creation # Test you cannot create an invalid criterion def test_criterion_order_and_description_are_required - stage = FactoryBot.create(:stage) - criterion = Criterion.new(stage: stage) + # stage = FactoryBot.create(:stage) + criterion = Criterion.create(stage: @stage) - refute criterion.valid? # "refute": fail if true + refute criterion.valid? # "refute": fail if true, pass if false # Validator is included in criterion model (@ doubtfire-api/app/models/feedback/criterion.rb) criterion.description = 'Criterion 1' - refute criterion.valid? + refute criterion.valid? # still shoul not be valid until order is added criterion.order = 1 assert criterion.valid? criterion.description = nil refute criterion.valid? + criterion.description = 'Criterion' + criterion.order = nil + refute criterion.valid? refute criterion.save # fail if criterion is saved end diff --git a/test/models/feedback/criterion_option_model_test.rb b/test/models/feedback/criterion_option_model_test.rb new file mode 100644 index 000000000..4b9b28284 --- /dev/null +++ b/test/models/feedback/criterion_option_model_test.rb @@ -0,0 +1,44 @@ +require 'test_helper' + +# +# Tests for CriterionOption model objects - not accessed via API +# +class CriterionOptionModelTest < ActiveSupport::TestCase + + # Setup objects for testing + setup do + DatabaseCleaner.start + @criterion = FactoryBot.create(:criterion) + @task_status = TaskStatus.new + end + + # Test you can create a valid criterion option + def test_valid_criterion_option_creation + criterion_option = CriterionOption.create(criterion: @criterion, task_status: @task_status) + assert criterion_option.valid? + criterion_option.resolved_message_text = Faker::Lorem.sentence + assert criterion_option.valid? + criterion_option.unresolved_message_text = Faker::Lorem.sentence + assert criterion_option.valid? + end + + # Test you cannot create an invalid criterion option + def test_invalid_criterion_option_creation + criterion_option = CriterionOption.new + + refute criterion_option.valid? + criterion_option.resolved_message_text = Faker::Lorem.sentence + refute criterion_option.valid? + criterion_option.unresolved_message_text = Faker::Lorem.sentence + refute criterion_option.valid? + + criterion_option.task_status = @task_status + refute criterion_option.valid? + criterion_option.criterion = @criterion + assert criterion_option.valid? + criterion_option.task_status = nil + refute criterion_option.valid? + + refute criterion_option.save + end +end diff --git a/test/models/feedback/feedback_comment_model_test.rb b/test/models/feedback/feedback_comment_model_test.rb new file mode 100644 index 000000000..bbec52f7a --- /dev/null +++ b/test/models/feedback/feedback_comment_model_test.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +# +# Contains tests for FeedbackComment model objects - not accessed via API +# +class FeedbackCommentModelTest < ActiveSupport::TestCase + + # Setup objects for testing + def setup + DatabaseCleaner.start + criterion = FactoryBot.create(:criterion) + task_status = TaskStatus.new + @criterion_option = CriterionOption.create(criterion: criterion, task_status: task_status) + + @task = Task.new + @user = FactoryBot.create(:user) + @recipient = FactoryBot.create(:user) + end + + # Test the creation of a valid feedback comment + def test_valid_feedback_comment_creation + feedback_comment = FeedbackComment.new(task: @task, user: @user, recipient: @recipient, comment: 'Test Comment', criterion_option: @criterion_option) + assert feedback_comment.valid? + end + + # Test the creation of an invalid feedback comment + def test_invalid_feedback_comment_creation + feedback_comment = FeedbackComment.new + refute feedback_comment.valid? + + feedback_comment.task = @task + refute feedback_comment.valid? + + feedback_comment.user = @user + refute feedback_comment.valid? + + feedback_comment.recipient = @recipient + refute feedback_comment.valid? + + feedback_comment.comment = 'Test Comment' + refute feedback_comment.valid? + + feedback_comment.criterion_option = @criterion_option + assert feedback_comment.valid? + + feedback_comment.task = nil + refute feedback_comment.valid? + + feedback_comment.task = @task + feedback_comment.user = nil + + refute feedback_comment.save + end +end diff --git a/test/models/feedback/feedback_comment_template_model_test.rb b/test/models/feedback/feedback_comment_template_model_test.rb new file mode 100644 index 000000000..a18ad22d9 --- /dev/null +++ b/test/models/feedback/feedback_comment_template_model_test.rb @@ -0,0 +1,41 @@ +require 'test_helper' + +# +# Contains tests for FeedbackCommentTemplate model objects - not accessed via API +# +class FeedbackCommentTemplateModelTest < ActiveSupport::TestCase + + # Setup objects for testing + def setup + DatabaseCleaner.start + task_status = TaskStatus.new + @criterion_option = CriterionOption.create(task_status: task_status) + end + + # Test you can create a valid feedback comment template + def test_valid_feedback_comment_template_creation + feedback_comment_template = FeedbackCommentTemplate.create(criterion_option: @criterion_option, comment_text_situation: 'This is the situation') + + assert feedback_comment_template.valid? + + assert feedback_comment_template.criterion_option == @criterion_option + assert feedback_comment_template.comment_text_situation == 'This is the situation' + end + + # Test you cannot create an invalid feedback comment template + def test_invalid_feedback_comment_template_creation + feedback_comment_template = FeedbackCommentTemplate.new + refute feedback_comment_template.valid? + + feedback_comment_template.comment_text_situation = 'This is a comment' + refute feedback_comment_template.valid? + + feedback_comment_template.criterion_option = @criterion_option + assert feedback_comment_template.valid? + + feedback_comment_template.comment_text_situation = nil + refute feedback_comment_template.valid? + + refute feedback_comment_template.save + end +end diff --git a/test/models/feedback/stage_model_test.rb b/test/models/feedback/stage_model_test.rb index 4f57be3c2..127e2e1d6 100644 --- a/test/models/feedback/stage_model_test.rb +++ b/test/models/feedback/stage_model_test.rb @@ -4,35 +4,53 @@ # Contains tests for Stage model objects - not accessed via API # class StageModelTest < ActiveSupport::TestCase - def app - Rails.application + + # # Set up variables for testing + setup do + @td = FactoryBot.create(:task_definition) + @title = Faker::Lorem.sentence + @order = Faker::Number.number(digits: 1) end # Test that you can create a valid stage - def test_stage_creation - td = FactoryBot.create(:task_definition) # FactoryBot is a gem that creates test data - stage = Stage.create(task_definition: td, title: 'Stage 1', order: 1) - - assert stage # "assert": pass if true, i.e. pass if stage exists - assert stage.task_definition # test that stage has a task definition - assert stage.title == 'Stage 1' # test that the stage has the correct title, i.e. 'Stage 1' - assert stage.order == 1 # test that the stage has the correct order, i.e. 1 + def test_valid_stage_creation + DatabaseCleaner.start + stage = Stage.create!(task_definition: @td, title: @title, order: @order) + + assert stage.valid? # "assert": pass if true, i.e. pass if stage exists + assert_equal @td, stage.task_definition + assert_equal @title, stage.title + assert_equal @order, stage.order end # Test that you cannot create an invalid stage - def test_stage_order_and_title_are_required - td = FactoryBot.create(:task_definition) - stage = Stage.new(task_definition: td) + def test_invalid_stage_creation + + # Test that stage is invalid without task definition id + stage = Stage.new(title: @title, order: @order) + refute stage.valid? # pass if stage does not exist - refute stage.valid? # "refute": fail if true, i.e. fail if stage is valid - # Validator is included - stage.title = 'Stage 1' + # Test that stage is invalid without title and order + stage = Stage.new(task_definition: @td) refute stage.valid? - stage.order = 1 + + # Test that stage is valid with both title and order + stage.title = @title + stage.order = @order assert stage.valid? + + # Test that stage is invalid with title and without order + stage.order = nil + refute stage.valid? + assert_includes stage.errors[:order], "can't be blank" + + # Test that stage is invalid with order and without title stage.title = nil + stage.order = @order refute stage.valid? + assert_includes stage.errors[:title], "can't be blank" + # Test that stage is unsaved refute stage.save # fail if stage is saved end -end +end \ No newline at end of file