diff --git a/spec/factories/course_condition_achievements.rb b/spec/factories/course_condition_achievements.rb index 4724b8766d8..8e86a452cef 100644 --- a/spec/factories/course_condition_achievements.rb +++ b/spec/factories/course_condition_achievements.rb @@ -3,5 +3,6 @@ class: Course::Condition::Achievement.name, aliases: [:achievement_condition] do course achievement + association :conditional, factory: :course_achievement end end diff --git a/spec/factories/course_condition_levels.rb b/spec/factories/course_condition_levels.rb index 1379c623ecb..141ef82e0f2 100644 --- a/spec/factories/course_condition_levels.rb +++ b/spec/factories/course_condition_levels.rb @@ -3,5 +3,6 @@ class: Course::Condition::Level.name, aliases: [:level_condition] do course minimum_level 1 + association :conditional, factory: :course_level end end diff --git a/spec/features/course/achievement_listing_spec.rb b/spec/features/course/achievement_listing_spec.rb index 7c8c5669a46..1f4bced670d 100644 --- a/spec/features/course/achievement_listing_spec.rb +++ b/spec/features/course/achievement_listing_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' -RSpec.describe 'Course: Achievements', type: :feature do - subject { page } +RSpec.feature 'Course: Achievements' do let!(:instance) { create(:instance) } @@ -20,8 +19,8 @@ visit course_achievements_path(course) end - context 'management buttons' do - it { is_expected.to have_link(nil, href: new_course_achievement_path(course)) } + it 'management buttons' do + expect(page).to have_link(nil, href: new_course_achievement_path(course)) end it 'shows all achievements' do diff --git a/spec/features/course/achievement_management_spec.rb b/spec/features/course/achievement_management_spec.rb index 444e6729b81..4322f9422d5 100644 --- a/spec/features/course/achievement_management_spec.rb +++ b/spec/features/course/achievement_management_spec.rb @@ -82,22 +82,60 @@ end end - scenario 'I can create an achievement condition' do - achievement = create(:course_achievement, course: course) - visit edit_course_achievement_path(course, achievement) - condition_achievement = create(:course_achievement, course: course) - expect(page).to have_selector(:link_or_button, - I18n.t('course.condition.achievements.new.header')) - click_link I18n.t('course.condition.achievements.new.header') - expect(current_path). - to eq(new_course_achievement_condition_achievement_path(course, achievement)) - find('#condition_achievement_achievement_id'). - find(:css, "option[value='#{condition_achievement.id}']"). - select_option - click_button I18n.t('helpers.submit.condition_achievement.create') - expect(current_path).to eq edit_course_achievement_path(course, achievement) - expect(page).to have_selector('tr.condition > td.achievement-condition-content', - text: condition_achievement.title) + describe 'I can create an achievement condition' do + scenario 'if there is a valid achievement which can serve as a condition' do + achievement = create(:course_achievement, course: course) + visit edit_course_achievement_path(course, achievement) + condition_achievement = create(:course_achievement, course: course) + expect(page).to have_selector(:link, + I18n.t('course.condition.achievements.new.header')) + click_link I18n.t('course.condition.achievements.new.header') + expect(current_path). + to eq(new_course_achievement_condition_achievement_path(course, achievement)) + find('#condition_achievement_achievement_id'). + find(:css, "option[value='#{condition_achievement.id}']"). + select_option + click_button I18n.t('helpers.submit.condition_achievement.create') + expect(current_path).to eq edit_course_achievement_path(course, achievement) + expect(page).to have_selector('tr.condition > td.level-condition-content', + text: condition_achievement.title) + end + + scenario 'unless there are no valid achievements' do + Course::Condition::Achievement.destroy_all + Course::Achievement.destroy_all + achievement = create(:course_achievement, course: course) + visit edit_course_achievement_path(course, achievement) + + # The creation link won't be shown + expect(page).not_to have_selector(:link, + I18n.t('course.condition.achievements.new.header')) + end + + scenario 'unless it has already been added or is the current one' do + _, achievement, other_achievement = create_achievement_condition + visit edit_course_achievement_path(course, achievement) + click_link I18n.t('course.condition.achievements.new.header') + expect(page).not_to have_selector('condition_achievement_achievement_id >' \ + "option[value='#{other_achievement.id}']") + expect(page).not_to have_selector('#condition_achievement_achievement_id >' \ + "option[value='#{achievement.id}']") + end + + scenario 'unless no achievement was selected' do + achievement = create(:course_achievement, course: course) + visit edit_course_achievement_path(course, achievement) + click_link I18n.t('course.condition.achievements.new.header') + expect(current_path). + to eq(new_course_achievement_condition_achievement_path(course, achievement)) + find('#condition_achievement_achievement_id'). + find(:css, "option[value='']").select_option + click_button I18n.t('helpers.submit.condition_achievement.create') + expect(current_path). + to eq(course_achievement_condition_achievements_path(course.id, achievement.id)) + expect(page). + to have_text(I18n.t('course.condition.errors.none_selected')) + end end scenario 'I can edit an achievement condition' do diff --git a/spec/models/course/condition/achievement_spec.rb b/spec/models/course/condition/achievement_spec.rb index a3b30e32be8..9564d8e8b23 100644 --- a/spec/models/course/condition/achievement_spec.rb +++ b/spec/models/course/condition/achievement_spec.rb @@ -2,4 +2,37 @@ RSpec.describe Course::Condition::Achievement, type: :model do it { is_expected.to act_as(:condition).class_name(Course::Condition.name) } + it { is_expected.to respond_to(:name) } + + let!(:instance) { create(:instance) } + with_tenant(:instance) do + let(:course) { create(:course) } + + describe 'validations' do + it 'is invalid without an achievement' do + expect(subject.valid?).to be_falsey + end + it 'is invalid when its achievement is its conditional, causing a circular reference' do + conditional = create(:course_achievement, course: course) + subject.achievement = conditional + subject.conditional = conditional + expect(subject.valid?).to be_falsey + end + it "is invalid when its achievement is included in its conditional's conditions" do + achievement = create(:course_achievement, course: course) + condition = create(:course_condition_achievement, course: course, achievement: achievement) + conditional = create(:course_achievement, course: course, conditions: [condition]) + subject.conditional = conditional + subject.achievement = achievement + expect(subject.valid?).to be_falsey + end + end + + describe '#name' do + it 'returns the title of the achievement' do + subject.achievement = create(:course_achievement, course: course) + expect(subject.name).to eq(subject.achievement.title) + end + end + end end diff --git a/spec/models/course/condition/level_spec.rb b/spec/models/course/condition/level_spec.rb index e5ff6929560..8ecdad2e68c 100644 --- a/spec/models/course/condition/level_spec.rb +++ b/spec/models/course/condition/level_spec.rb @@ -2,4 +2,10 @@ RSpec.describe Course::Condition::Level, type: :model do it { is_expected.to act_as(:condition).class_name(Course::Condition.name) } + it { is_expected.to respond_to(:name) } + + it do + subject.minimum_level = 10 + expect(subject.name).to eq('Level 10') + end end