# frozen_string_literal: true require "wizard" RSpec.describe Wizard do fab!(:admin) { Fabricate(:admin) } before { SiteSetting.wizard_enabled = true } describe "defaults" do it "has default values" do wizard = Wizard.new(Fabricate.build(:moderator)) expect(wizard.steps).to be_empty expect(wizard.user).to be_present end end describe "append_step" do let(:user) { Fabricate.build(:moderator) } let(:wizard) { Wizard.new(user) } let(:step1) { wizard.create_step("first-step") } let(:step2) { wizard.create_step("second-step") } it "works with a block format" do wizard.append_step("wat") { |step| expect(step).to be_present } expect(wizard.steps.size).to eq(1) end it "adds the step correctly" do expect(step1.index).to be_blank wizard.append_step(step1) expect(wizard.steps.size).to eq(1) expect(wizard.start).to eq(step1) expect(step1.next).to be_blank expect(step1.previous).to be_blank expect(step1.index).to eq(0) expect(step1.fields).to be_empty field = step1.add_field(id: "test", type: "text") expect(step1.fields).to eq([field]) end it "sequences multiple steps" do wizard.append_step(step1) wizard.append_step(step2) expect(wizard.steps.size).to eq(2) expect(wizard.start).to eq(step1) expect(step1.next).to eq(step2) expect(step1.previous).to be_blank expect(step2.previous).to eq(step1) expect(step1.index).to eq(0) expect(step2.index).to eq(1) end end describe "remove_step" do let(:user) { Fabricate.build(:moderator) } let(:wizard) { Wizard.new(user) } let(:step1) { wizard.create_step("first-step") } let(:step2) { wizard.create_step("second-step") } let(:step3) { wizard.create_step("third-step") } before do wizard.append_step(step1) wizard.append_step(step2) wizard.append_step(step3) end it "does nothing if step id doesn't match any steps" do wizard.remove_step("nope") expect(wizard.steps).to contain_exactly(step1, step2, step3) expect(wizard.start).to eq(step1) end it "can remove the first step" do wizard.remove_step(step1.id) expect(wizard.steps).to contain_exactly(step2, step3) expect(step2.index).to eq(0) expect(step2.previous).to be_blank expect(step2.next).to eq(step3) expect(step3.index).to eq(1) expect(step3.previous).to eq(step2) expect(step3.next).to be_blank expect(wizard.start).to eq(step2) end it "can remove a middle step" do wizard.remove_step(step2.id) expect(wizard.steps).to contain_exactly(step1, step3) expect(step1.index).to eq(0) expect(step1.previous).to be_blank expect(step1.next).to eq(step3) expect(step3.index).to eq(1) expect(step3.previous).to eq(step1) expect(step3.next).to be_blank expect(wizard.start).to eq(step1) end it "can remove the last step" do wizard.remove_step(step3.id) expect(wizard.steps).to contain_exactly(step1, step2) expect(step1.index).to eq(0) expect(step1.previous).to be_blank expect(step1.next).to eq(step2) expect(step2.index).to eq(1) expect(step2.previous).to eq(step1) expect(step2.next).to be_blank expect(wizard.start).to eq(step1) end end describe ".exclude_step" do let(:user) { Fabricate.build(:moderator) } let(:wizard) { Wizard.new(user) } it "excludes steps even if they are added via append_step" do wizard.append_step("first") { |step| step.add_field(id: "another_element", type: "text") } Wizard.exclude_step("random-step123") wizard.append_step("random-step123") do |step| step.add_field(id: "another_element", type: "text") end wizard.append_step("finished") expect(wizard.steps.map(&:id)).to eq(%w[first finished]) end end describe "#append_step with after specified" do let(:user) { Fabricate.build(:moderator) } let(:wizard) { Wizard.new(user) } it "inserts steps after the proper step" do wizard.append_step("first") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("second") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("actually-second", after: "first") do |step| step.add_field(id: "another_element", type: "text") end expect(wizard.steps.sort_by(&:index).map(&:id)).to eq(%w[first actually-second second]) expect(wizard.steps.map(&:index).sort).to eq([0, 1, 2]) end it "inserts steps at the end if the after value does not match an existing step" do wizard.append_step("first") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("second") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("should_be_last", after: "abcdefghi") do |step| step.add_field(id: "another_element", type: "text") end expect(wizard.steps.sort_by(&:index).map(&:id)).to eq(%w[first second should_be_last]) expect(wizard.steps.map(&:index).sort).to eq([0, 1, 2]) end it "inserts steps at the end" do wizard.append_step("first") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("second") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("last", after: "second") do |step| step.add_field(id: "another_element", type: "text") end expect(wizard.steps.sort_by(&:index).map(&:id)).to eq(%w[first second last]) expect(wizard.steps.map(&:index).sort).to eq([0, 1, 2]) end end describe "completed?" do let(:user) { Fabricate.build(:moderator) } let(:wizard) { Wizard.new(user) } it "is complete when all steps with fields have logs" do wizard.append_step("first") { |step| step.add_field(id: "element", type: "text") } wizard.append_step("second") { |step| step.add_field(id: "another_element", type: "text") } wizard.append_step("finished") expect(wizard.start.id).to eq("first") expect(wizard.completed_steps?("first")).to eq(false) expect(wizard.completed_steps?("second")).to eq(false) expect(wizard.completed?).to eq(false) updater = wizard.create_updater("first", element: "test") updater.update expect(wizard.start.id).to eq("second") expect(wizard.completed_steps?("first")).to eq(true) expect(wizard.completed?).to eq(false) updater = wizard.create_updater("second", element: "test") updater.update expect(wizard.completed_steps?("first")).to eq(true) expect(wizard.completed_steps?("second")).to eq(true) expect(wizard.completed_steps?("finished")).to eq(false) expect(wizard.completed?).to eq(true) # Once you've completed the wizard start at the beginning expect(wizard.start.id).to eq("first") end end describe "#requires_completion?" do def build_simple(user) wizard = Wizard.new(user) wizard.append_step("simple") { |step| step.add_field(id: "name", type: "text") } wizard end it "is false for anonymous" do expect(build_simple(nil).requires_completion?).to eq(false) end it "is false for regular users" do expect(build_simple(Fabricate.build(:user)).requires_completion?).to eq(false) end it "it's false when the wizard is disabled" do SiteSetting.wizard_enabled = false expect(build_simple(admin).requires_completion?).to eq(false) end it "its false when the wizard is bypassed" do SiteSetting.bypass_wizard_check = true expect(build_simple(admin).requires_completion?).to eq(false) end it "its automatically bypasses after you reach topic limit" do Fabricate(:topic) wizard = build_simple(admin) wizard.max_topics_to_require_completion = Topic.count - 1 expect(wizard.requires_completion?).to eq(false) expect(SiteSetting.bypass_wizard_check).to eq(true) end it "it's true for the first admin who logs in" do second_admin = Fabricate(:admin) UserAuthToken.generate!(user_id: second_admin.id) expect(build_simple(admin).requires_completion?).to eq(false) expect(build_simple(second_admin).requires_completion?).to eq(true) end it "is false for staff when complete" do wizard = build_simple(admin) updater = wizard.create_updater("simple", name: "Evil Trout") updater.update expect(wizard.requires_completion?).to eq(false) # It's also false for another user wizard = build_simple(admin) expect(wizard.requires_completion?).to eq(false) end end end