From d3c6733e59c73508da3746681c5d8b39bde55d28 Mon Sep 17 00:00:00 2001 From: angusmcleod Date: Thu, 17 Jun 2021 17:50:22 +1000 Subject: [PATCH] Abstract and improve submission handling --- config/locales/server.en.yml | 4 +- .../custom_wizard/admin/submissions.rb | 26 ++---- controllers/custom_wizard/steps.rb | 10 +-- controllers/custom_wizard/wizard.rb | 5 +- extensions/invites_controller.rb | 2 +- jobs/set_after_time_wizard.rb | 2 +- lib/custom_wizard/action.rb | 54 +++++------ lib/custom_wizard/builder.rb | 35 ++++---- lib/custom_wizard/submission.rb | 89 +++++++++++++++++++ lib/custom_wizard/wizard.rb | 85 +++++++----------- plugin.rb | 7 +- serializers/custom_wizard/submission.rb | 13 +++ spec/components/custom_wizard/action_spec.rb | 10 +-- spec/components/custom_wizard/builder_spec.rb | 28 +++--- .../custom_wizard/submission_spec.rb | 43 +++++++++ spec/components/custom_wizard/wizard_spec.rb | 25 +----- .../admin/submissions_controller_spec.rb | 37 ++++---- .../custom_wizard/steps_controller_spec.rb | 8 +- .../custom_wizard/wizard_controller_spec.rb | 5 +- 19 files changed, 292 insertions(+), 196 deletions(-) create mode 100644 lib/custom_wizard/submission.rb create mode 100644 serializers/custom_wizard/submission.rb create mode 100644 spec/components/custom_wizard/submission_spec.rb diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 4bda825a..7e507450 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1,8 +1,8 @@ en: admin: wizard: - submissions: - no_user: "deleted (id: %{id})" + submission: + no_user: "deleted (user_id: %{user_id})" wizard: custom_title: "Wizard" diff --git a/controllers/custom_wizard/admin/submissions.rb b/controllers/custom_wizard/admin/submissions.rb index 5467587e..682c4030 100644 --- a/controllers/custom_wizard/admin/submissions.rb +++ b/controllers/custom_wizard/admin/submissions.rb @@ -13,34 +13,20 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController def show render_json_dump( wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false), - submissions: build_submissions.as_json + submissions: ActiveModel::ArraySerializer.new(ordered_submissions, each_serializer: CustomWizard::SubmissionSerializer) ) end def download - send_data build_submissions.to_json, + send_data ordered_submissions.to_json, filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json", content_type: "application/json", disposition: "attachment" end + + protected - private - - def build_submissions - PluginStoreRow.where(plugin_name: "#{@wizard.id}_submissions") - .order('id DESC') - .map do |row| - value = ::JSON.parse(row.value) - - if user = User.find_by(id: row.key) - username = user.username - else - username = I18n.t('admin.wizard.submissions.no_user', id: row.key) - end - - value.map do |v| - { username: username }.merge!(v.except("redirect_to")) - end - end.flatten + def ordered_submissions + CustomWizard::Submission.list(@wizard, order_by: 'id') end end diff --git a/controllers/custom_wizard/steps.rb b/controllers/custom_wizard/steps.rb index aa4fbd7f..9c0fbf92 100644 --- a/controllers/custom_wizard/steps.rb +++ b/controllers/custom_wizard/steps.rb @@ -28,7 +28,7 @@ class CustomWizard::StepsController < ::ApplicationController current_step = @wizard.find_step(update[:step_id]) current_submission = @wizard.current_submission result = {} - @wizard.filter_conditional_fields + if current_step.conditional_final_step && !current_step.last_step current_step.force_final = true end @@ -44,7 +44,7 @@ class CustomWizard::StepsController < ::ApplicationController end end - @wizard.save_submission(current_submission) + current_submission.save if redirect = get_redirect updater.result[:redirect_on_complete] = redirect @@ -101,9 +101,9 @@ class CustomWizard::StepsController < ::ApplicationController def get_redirect return @result[:redirect_on_next] if @result[:redirect_on_next].present? - current_submission = @wizard.current_submission - return nil unless current_submission.present? + submission = @wizard.current_submission + return nil unless submission.present? ## route_to set by actions, redirect_on_complete set by actions, redirect_to set at wizard entry - current_submission[:route_to] || current_submission[:redirect_on_complete] || current_submission[:redirect_to] + submission.route_to || submission.redirect_on_complete || submission.redirect_to end end diff --git a/controllers/custom_wizard/wizard.rb b/controllers/custom_wizard/wizard.rb index 9670fd62..e682a307 100644 --- a/controllers/custom_wizard/wizard.rb +++ b/controllers/custom_wizard/wizard.rb @@ -63,8 +63,9 @@ class CustomWizard::WizardController < ::ApplicationController if user && wizard.can_access? submission = wizard.current_submission - if submission && submission['redirect_to'] - result.merge!(redirect_to: submission['redirect_to']) + + if submission && submission.redirect_to + result.merge!(redirect_to: submission.redirect_to) end wizard.final_cleanup! diff --git a/extensions/invites_controller.rb b/extensions/invites_controller.rb index cafb15bd..5e0094da 100644 --- a/extensions/invites_controller.rb +++ b/extensions/invites_controller.rb @@ -5,7 +5,7 @@ module InvitesControllerCustomWizard wizard_id = @user.custom_fields['redirect_to_wizard'] if wizard_id && url != '/' - CustomWizard::Wizard.set_submission_redirect(@user, wizard_id, url) + CustomWizard::Wizard.set_wizard_redirect(@user, wizard_id, url) url = "/w/#{wizard_id.dasherize}" end end diff --git a/jobs/set_after_time_wizard.rb b/jobs/set_after_time_wizard.rb index 3b2e9e11..7a5b86c6 100644 --- a/jobs/set_after_time_wizard.rb +++ b/jobs/set_after_time_wizard.rb @@ -9,7 +9,7 @@ module Jobs user_ids = [] User.human_users.each do |user| - if CustomWizard::Wizard.set_wizard_redirect(wizard.id, user) + if CustomWizard::Wizard.set_user_redirect(wizard.id, user) user_ids.push(user.id) end end diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index 5388a326..acb8dafb 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true class CustomWizard::Action - attr_accessor :data, + attr_accessor :submission, :action, :user, :guardian, @@ -11,7 +11,7 @@ class CustomWizard::Action @action = opts[:action] @user = @wizard.user @guardian = Guardian.new(@user) - @data = opts[:data] + @submission = opts[:submission] @log = [] @result = CustomWizard::ActionResult.new end @@ -26,14 +26,18 @@ class CustomWizard::Action end if @result.success? && @result.output.present? - data[action['id']] = @result.output + @submission.fields[action['id']] = @result.output end save_log end + def mapper_data + @mapper_data ||= @submission&.fields_and_meta || {} + end + def mapper - @mapper ||= CustomWizard::Mapper.new(user: user, data: data) + @mapper ||= CustomWizard::Mapper.new(user: user, data: mapper_data) end def create_topic @@ -47,7 +51,7 @@ class CustomWizard::Action messages = creator.errors.full_messages.join(" ") log_error("failed to create", messages) elsif action['skip_redirect'].blank? - data['redirect_on_complete'] = post.topic.url + @submission.redirect_on_complete = post.topic.url end if creator.errors.blank? @@ -65,7 +69,7 @@ class CustomWizard::Action if action['required'].present? required = CustomWizard::Mapper.new( inputs: action['required'], - data: data, + data: mapper_data, user: user ).perform @@ -79,7 +83,7 @@ class CustomWizard::Action targets = CustomWizard::Mapper.new( inputs: action['recipient'], - data: data, + data: mapper_data, user: user, multiple: true ).perform @@ -115,7 +119,7 @@ class CustomWizard::Action messages = creator.errors.full_messages.join(" ") log_error("failed to create message", messages) elsif action['skip_redirect'].blank? - data['redirect_on_complete'] = post.topic.url + @submission.redirect_on_complete = post.topic.url end if creator.errors.blank? @@ -178,7 +182,7 @@ class CustomWizard::Action def watch_categories watched_categories = CustomWizard::Mapper.new( inputs: action['categories'], - data: data, + data: mapper_data, user: user ).perform @@ -193,7 +197,7 @@ class CustomWizard::Action mute_remainder = CustomWizard::Mapper.new( inputs: action['mute_remainder'], - data: data, + data: mapper_data, user: user ).perform @@ -202,7 +206,7 @@ class CustomWizard::Action if action['usernames'] mapped_users = CustomWizard::Mapper.new( inputs: action['usernames'], - data: data, + data: mapper_data, user: user ).perform @@ -284,7 +288,7 @@ class CustomWizard::Action end route_to = Discourse.base_uri + url - @result.output = data['route_to'] = route_to + @result.output = @submission.route_to = route_to log_success("route: #{route_to}") else @@ -295,7 +299,7 @@ class CustomWizard::Action def add_to_group group_map = CustomWizard::Mapper.new( inputs: action['group'], - data: data, + data: mapper_data, user: user, opts: { multiple: true @@ -345,18 +349,18 @@ class CustomWizard::Action else url = CustomWizard::Mapper.new( inputs: url_input, - data: data, + data: mapper_data, user: user ).perform end if action['code'] - data[action['code']] = SecureRandom.hex(8) - url += "&#{action['code']}=#{data[action['code']]}" + @submission.fields[action['code']] = SecureRandom.hex(8) + url += "&#{action['code']}=#{@submission.fields[action['code']]}" end route_to = UrlHelper.encode(url) - data['route_to'] = route_to + @submission.route_to = route_to log_info("route: #{route_to}") end @@ -416,7 +420,7 @@ class CustomWizard::Action def action_category output = CustomWizard::Mapper.new( inputs: action['category'], - data: data, + data: mapper_data, user: user ).perform @@ -434,7 +438,7 @@ class CustomWizard::Action def action_tags output = CustomWizard::Mapper.new( inputs: action['tags'], - data: data, + data: mapper_data, user: user, ).perform @@ -451,7 +455,7 @@ class CustomWizard::Action if (custom_fields = action['custom_fields']).present? field_map = CustomWizard::Mapper.new( inputs: custom_fields, - data: data, + data: mapper_data, user: user ).perform registered_fields = CustomWizard::CustomField.full_list @@ -513,7 +517,7 @@ class CustomWizard::Action params[:title] = CustomWizard::Mapper.new( inputs: action['title'], - data: data, + data: mapper_data, user: user ).perform @@ -525,7 +529,7 @@ class CustomWizard::Action wizard: true, template: true ) : - data[action['post']] + @submission.fields[action['post']] params[:import_mode] = ActiveRecord::Type::Boolean.new.cast(action['suppress_notifications']) @@ -548,7 +552,7 @@ class CustomWizard::Action unless action[field].nil? || action[field] == "" params[field.to_sym] = CustomWizard::Mapper.new( inputs: action[field], - data: data, + data: mapper_data, user: user ).perform end @@ -587,7 +591,7 @@ class CustomWizard::Action if input.present? value = CustomWizard::Mapper.new( inputs: input, - data: data, + data: mapper_data, user: user ).perform @@ -617,7 +621,7 @@ class CustomWizard::Action if action[attr].present? value = CustomWizard::Mapper.new( inputs: action[attr], - data: data, + data: mapper_data, user: user ).perform diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb index a9fc6263..b5c04c27 100644 --- a/lib/custom_wizard/builder.rb +++ b/lib/custom_wizard/builder.rb @@ -24,7 +24,7 @@ class CustomWizard::Builder def mapper CustomWizard::Mapper.new( user: @wizard.user, - data: @wizard.current_submission + data: @wizard.current_submission&.fields_and_meta ) end @@ -47,9 +47,8 @@ class CustomWizard::Builder step.on_update do |updater| @updater = updater - @submission = (@wizard.current_submission || {}) - .merge(@updater.submission) - .with_indifferent_access + @submission = @wizard.current_submission || CustomWizard::Submission.new(@wizard) + @submission.fields.merge(@updater.submission) @updater.validate next if @updater.errors.any? @@ -60,13 +59,11 @@ class CustomWizard::Builder run_step_actions if @updater.errors.empty? - if route_to = @submission['route_to'] - @submission.delete('route_to') - end + route_to = @submission.route_to + @submission.route_to = nil + @submission.save - @wizard.save_submission(@submission) @updater.result[:redirect_on_next] = route_to if route_to - true else false @@ -93,7 +90,7 @@ class CustomWizard::Builder params[:value] = prefill_field(field_template, step_template) if !build_opts[:reset] && (submission = @wizard.current_submission) - params[:value] = submission[field_template['id']] if submission[field_template['id']] + params[:value] = submission.fields[field_template['id']] if submission.fields[field_template['id']] end if field_template['type'] === 'group' && params[:value].present? @@ -136,7 +133,7 @@ class CustomWizard::Builder content = CustomWizard::Mapper.new( inputs: content_inputs, user: @wizard.user, - data: @wizard.current_submission, + data: @wizard.current_submission&.fields_and_meta, opts: { with_type: true } @@ -171,7 +168,7 @@ class CustomWizard::Builder index = CustomWizard::Mapper.new( inputs: field_template['index'], user: @wizard.user, - data: @wizard.current_submission + data: @wizard.current_submission&.fields_and_meta ).perform params[:index] = index.to_i unless index.nil? @@ -195,7 +192,7 @@ class CustomWizard::Builder CustomWizard::Mapper.new( inputs: prefill, user: @wizard.user, - data: @wizard.current_submission + data: @wizard.current_submission&.fields_and_meta ).perform end end @@ -205,7 +202,7 @@ class CustomWizard::Builder result = CustomWizard::Mapper.new( inputs: template['condition'], user: @wizard.user, - data: @wizard.current_submission, + data: @wizard.current_submission&.fields_and_meta, opts: { multiple: true } @@ -275,7 +272,7 @@ class CustomWizard::Builder permitted_data = {} submission_key = nil params_key = nil - submission = @wizard.current_submission || {} + submission = @wizard.current_submission || CustomWizard::Submission.new(@wizard) permitted_params.each do |pp| pair = pp['pairs'].first @@ -283,11 +280,11 @@ class CustomWizard::Builder submission_key = pair['value'].to_sym if submission_key && params_key - submission[submission_key] = params[params_key] + submission.fields[submission_key] = params[params_key] end end - @wizard.save_submission(submission) + submission.save end def ensure_required_data(step, step_template) @@ -302,7 +299,7 @@ class CustomWizard::Builder end pairs.each do |pair| - pair['key'] = @wizard.current_submission[pair['key']] + pair['key'] = @wizard.current_submission.fields[pair['key']] end if !mapper.validate_pairs(pairs) @@ -329,7 +326,7 @@ class CustomWizard::Builder CustomWizard::Action.new( action: action_template, wizard: @wizard, - data: @submission + submission: @submission ).perform end end diff --git a/lib/custom_wizard/submission.rb b/lib/custom_wizard/submission.rb new file mode 100644 index 00000000..8cb06a4a --- /dev/null +++ b/lib/custom_wizard/submission.rb @@ -0,0 +1,89 @@ +class CustomWizard::Submission + include ActiveModel::SerializerSupport + + KEY ||= "submissions" + ACTION_KEY ||= "action" + META ||= %w(submitted_at route_to redirect_on_complete redirect_to) + + attr_reader :id, + :user, + :wizard + + attr_accessor :fields + + META.each do |attr| + class_eval { attr_accessor attr } + end + + def initialize(wizard, data = {}, user_id = nil) + @wizard = wizard + + if user_id + @user = User.find_by(id: user_id) || OpenStruct.new(deleted: true, id: user_id) + else + @user = wizard.user + end + + data = data.with_indifferent_access + @id = data['id'] || SecureRandom.hex(12) + @fields = data.except(META + ['id']) || {} + + META.each do |attr| + send("#{attr}=", data[attr]) if data[attr] + end + end + + def save + return nil unless wizard.save_submissions + validate_fields + + submissions = self.class.list(wizard, user_id: user.id).select { |s| s.id != self.id } + submissions.push(self) + + submission_data = submissions.map { |s| s.fields_and_meta } + PluginStore.set("#{wizard.id}_#{KEY}", user.id, submission_data) + end + + def validate_fields + self.fields = fields.select do |key, value| + wizard.field_ids.include?(key) || key.include?(ACTION_KEY) + end + end + + def fields_and_meta + result = fields + + META.each do |attr| + if value = self.send(attr) + result[attr] = value + end + end + + result + end + + def self.get(wizard, user_id) + data = PluginStore.get("#{wizard.id}_#{KEY}", user_id).first + new(wizard, data, user_id) + end + + def self.list(wizard, user_id: nil, order_by: nil) + params = { plugin_name: "#{wizard.id}_#{KEY}" } + params[:key] = user_id if user_id.present? + + query = PluginStoreRow.where(params) + query = query.order("#{order_by} DESC") if order_by.present? + + result = [] + + query.each do |record| + if (submission_data = ::JSON.parse(record.value)).any? + submission_data.each do |data| + result.push(new(wizard, data, record.key)) + end + end + end + + result + end +end \ No newline at end of file diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb index f92f3d61..fff7d159 100644 --- a/lib/custom_wizard/wizard.rb +++ b/lib/custom_wizard/wizard.rb @@ -29,7 +29,8 @@ class CustomWizard::Wizard :first_step, :start, :actions, - :user + :user, + :submissions def initialize(attrs = {}, user = nil) @user = user @@ -221,72 +222,38 @@ class CustomWizard::Wizard @groups ||= ::Site.new(Guardian.new(user)).groups end + def field_ids + steps.map { |step| step.fields.map { |field| field.id } }.flatten + end + def submissions return nil unless user.present? - @submissions ||= Array.wrap(PluginStore.get("#{id}_submissions", user.id)) + @submissions ||= CustomWizard::Submission.list(self, user_id: user.id) end def current_submission - if submissions.present? && submissions.last.present? && !submissions.last.key?("submitted_at") - submissions.last.with_indifferent_access - else - nil + @current_submission ||= begin + if submissions.present? + unsubmitted = submissions.select { |submission| !submission.submitted_at } + unsubmitted.present? ? unsubmitted.first : nil + else + nil + end end end - def set_submissions(submissions) - PluginStore.set("#{id}_submissions", user.id, Array.wrap(submissions)) - @submissions = nil - end - - def save_submission(submission) - return nil unless save_submissions - - submissions.pop(1) if unfinished? - submissions.push(submission) - set_submissions(submissions) - end - - def filter_conditional_fields - included_fields = steps.map { |s| s.fields.map { |f| f.id } }.flatten - filtered_submision = current_submission&.select do |key, _| - key = key.to_s - included_fields.include?(key) || - required_fields.include?(key) || - key.include?("action") - end - - save_submission(filtered_submision) - end - - def required_fields - %w{ - submitted_at - route_to - saved_param - } - end - def final_cleanup! if id == user.custom_fields['redirect_to_wizard'] user.custom_fields.delete('redirect_to_wizard') user.save_custom_fields(true) end - if submission = current_submission - submission['submitted_at'] = Time.now.iso8601 - save_submission(submission) + if current_submission.present? + current_submission.submitted_at = Time.now.iso8601 + current_submission.save end end - def self.submissions(wizard_id, user) - new({ id: wizard_id }, user).submissions - end - - def self.set_submissions(wizard_id, user, submissions) - new({ id: wizard_id }, user).set_submissions(submissions) - end - def self.create(wizard_id, user = nil) if template = CustomWizard::Template.find(wizard_id) new(template.to_h, user) @@ -339,11 +306,7 @@ class CustomWizard::Wizard end end - def self.set_submission_redirect(user, wizard_id, url) - set_submissions(wizard_id, user, [{ redirect_to: url }]) - end - - def self.set_wizard_redirect(wizard_id, user) + def self.set_user_redirect(wizard_id, user) wizard = self.create(wizard_id, user) if wizard.permitted? @@ -353,4 +316,16 @@ class CustomWizard::Wizard false end end + + def self.set_wizard_redirect(user, wizard_id, url) + wizard = self.create(wizard_id, user) + + if wizard.permitted? + submission = wizard.current_submission || CustomWizard::Submission.new(wizard) + submission.redirect_to = url + submission.save + else + false + end + end end diff --git a/plugin.rb b/plugin.rb index a4278f65..ecbf850a 100644 --- a/plugin.rb +++ b/plugin.rb @@ -66,6 +66,7 @@ after_initialize do ../lib/custom_wizard/log.rb ../lib/custom_wizard/step_updater.rb ../lib/custom_wizard/step.rb + ../lib/custom_wizard/submission.rb ../lib/custom_wizard/template.rb ../lib/custom_wizard/wizard.rb ../lib/custom_wizard/api/api.rb @@ -110,7 +111,7 @@ after_initialize do if !wizard.completed? custom_redirect = true - CustomWizard::Wizard.set_wizard_redirect(wizard.id, user) + CustomWizard::Wizard.set_user_redirect(wizard.id, user) end end @@ -131,7 +132,7 @@ after_initialize do on(:user_approved) do |user| if wizard = CustomWizard::Wizard.after_signup(user) - CustomWizard::Wizard.set_wizard_redirect(wizard.id, user) + CustomWizard::Wizard.set_user_redirect(wizard.id, user) end end @@ -142,7 +143,7 @@ after_initialize do if request.format === 'text/html' && !@excluded_routes.any? { |str| /#{str}/ =~ url } && wizard_id if request.referer !~ /\/w\// && request.referer !~ /\/invites\// - CustomWizard::Wizard.set_submission_redirect(current_user, wizard_id, request.referer) + CustomWizard::Wizard.set_wizard_redirect(current_user, wizard_id, request.referer) end if CustomWizard::Template.exists?(wizard_id) redirect_to "/w/#{wizard_id.dasherize}" diff --git a/serializers/custom_wizard/submission.rb b/serializers/custom_wizard/submission.rb new file mode 100644 index 00000000..bb8bc288 --- /dev/null +++ b/serializers/custom_wizard/submission.rb @@ -0,0 +1,13 @@ +class CustomWizard::SubmissionSerializer + attributes :id, + :username, + :fields, + :redirect_to, + :submitted_at + + def username + object.user.deleted ? + I18n.t('admin.wizard.submission.no_user', user_id: object.user.id) : + object.user.username + end +end \ No newline at end of file diff --git a/spec/components/custom_wizard/action_spec.rb b/spec/components/custom_wizard/action_spec.rb index 9910c0bd..6f77d617 100644 --- a/spec/components/custom_wizard/action_spec.rb +++ b/spec/components/custom_wizard/action_spec.rb @@ -182,7 +182,7 @@ describe CustomWizard::Action do updater = wizard.create_updater(wizard.steps[1].id, {}) updater.update - category = Category.find_by(id: wizard.current_submission['action_8']) + category = Category.find_by(id: wizard.current_submission.fields['action_8']) expect(updater.result[:redirect_on_next]).to eq( "/new-topic?title=Title%20of%20the%20composer%20topic&body=I%20am%20interpolating%20some%20user%20fields%20Angus%20angus%20angus%40email.com&category_id=#{category.id}&tags=tag1" @@ -215,20 +215,20 @@ describe CustomWizard::Action do wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update wizard.create_updater(wizard.steps[1].id, {}).update - expect(Category.where(id: wizard.current_submission['action_8']).exists?).to eq(true) + expect(Category.where(id: wizard.current_submission.fields['action_8']).exists?).to eq(true) end it 'creates a group' do wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update - expect(Group.where(name: wizard.current_submission['action_9']).exists?).to eq(true) + expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true) end it 'adds a user to a group' do wizard = CustomWizard::Builder.new(@template[:id], user).build step_id = wizard.steps[0].id updater = wizard.create_updater(step_id, step_1_field_1: "Text input").update - group = Group.find_by(name: wizard.current_submission['action_9']) + group = Group.find_by(name: wizard.current_submission.fields['action_9']) expect(group.users.first.username).to eq('angus') end @@ -237,7 +237,7 @@ describe CustomWizard::Action do wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update wizard.create_updater(wizard.steps[1].id, {}).update expect(CategoryUser.where( - category_id: wizard.current_submission['action_8'], + category_id: wizard.current_submission.fields['action_8'], user_id: user.id ).first.notification_level).to eq(2) expect(CategoryUser.where( diff --git a/spec/components/custom_wizard/builder_spec.rb b/spec/components/custom_wizard/builder_spec.rb index d9d3524e..0504a238 100644 --- a/spec/components/custom_wizard/builder_spec.rb +++ b/spec/components/custom_wizard/builder_spec.rb @@ -189,7 +189,10 @@ describe CustomWizard::Builder do context "user has partially completed" do before do wizard = CustomWizard::Wizard.new(@template, user) - wizard.set_submissions(step_1_field_1: 'I am a user submission') + data = { + step_1_field_1: 'I am a user submission' + } + CustomWizard::Submission.new(wizard, data).save end it 'returns saved submissions' do @@ -253,9 +256,12 @@ describe CustomWizard::Builder do end it 'is permitted if required data is present' do - CustomWizard::Wizard.set_submissions('super_mega_fun_wizard', user, - required_data: "required_value" - ) + wizard = CustomWizard::Wizard.create('super_mega_fun_wizard', user) + data = { + step_1_field_1: 'I am a user submission' + } + CustomWizard::Submission.new(wizard, data).save + expect( CustomWizard::Builder.new(@template[:id], user).build .steps.first @@ -336,31 +342,27 @@ describe CustomWizard::Builder do context 'on update' do def perform_update(step_id, submission) - wizard = CustomWizard::Builder.new(@template[:id], user).build - updater = wizard.create_updater(step_id, submission) + updater = @wizard.create_updater(step_id, submission) updater.update updater end it 'saves submissions' do + @wizard = CustomWizard::Builder.new(@template[:id], user).build perform_update('step_1', step_1_field_1: 'Text input') - expect( - CustomWizard::Wizard.submissions(@template[:id], user) - .first['step_1_field_1'] - ).to eq('Text input') + expect(@wizard.current_submission.fields['step_1_field_1']).to eq('Text input') end context 'save submissions disabled' do before do @template[:save_submissions] = false CustomWizard::Template.save(@template.as_json) + @wizard = CustomWizard::Builder.new(@template[:id], user).build end it "does not save submissions" do perform_update('step_1', step_1_field_1: 'Text input') - expect( - CustomWizard::Wizard.submissions(@template[:id], user).first - ).to eq(nil) + expect(@wizard.current_submission).to eq(nil) end end end diff --git a/spec/components/custom_wizard/submission_spec.rb b/spec/components/custom_wizard/submission_spec.rb new file mode 100644 index 00000000..798a2969 --- /dev/null +++ b/spec/components/custom_wizard/submission_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true +require_relative '../../plugin_helper' + +describe CustomWizard::Submission do + fab!(:user) { Fabricate(:user) } + fab!(:user2) { Fabricate(:user) } + + let(:template_json) { + JSON.parse(File.open( + "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" + ).read) + } + + before do + CustomWizard::Template.save(template_json, skip_jobs: true) + + template_json_2 = template_json.dup + template_json_2["id"] = "super_mega_fun_wizard_2" + CustomWizard::Template.save(template_json_2, skip_jobs: true) + + @wizard = CustomWizard::Wizard.create(template_json["id"], user) + @wizard2 = CustomWizard::Wizard.create(template_json["id"], user2) + @wizard3 = CustomWizard::Wizard.create(template_json_2["id"], user) + + described_class.new(@wizard, step_1_field_1: "I am a user submission").save + described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save + described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save + end + + it "saves a user's submission" do + expect( + described_class.get(template_json["id"], user.id).fields["step_1_field_1"] + ).to eq("I am a user submission") + end + + it "list submissions by wizard" do + expect(described_class.list(@wizard).size).to eq(2) + end + + it "list submissions by wizard and user" do + expect(described_class.list(@wizard, user).size).to eq(1) + end +end \ No newline at end of file diff --git a/spec/components/custom_wizard/wizard_spec.rb b/spec/components/custom_wizard/wizard_spec.rb index 9808f32f..376fce2c 100644 --- a/spec/components/custom_wizard/wizard_spec.rb +++ b/spec/components/custom_wizard/wizard_spec.rb @@ -204,14 +204,7 @@ describe CustomWizard::Wizard do context "submissions" do before do - @wizard.set_submissions(step_1_field_1: 'I am a user submission') - end - - it "sets the user's submission" do - expect( - PluginStore.get("#{template_json['id']}_submissions", user.id) - .first['step_1_field_1'] - ).to eq('I am a user submission') + CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission") end it "lists the user's submissions" do @@ -219,20 +212,10 @@ describe CustomWizard::Wizard do end it "returns the user's current submission" do - expect(@wizard.current_submission['step_1_field_1']).to eq('I am a user submission') + expect(@wizard.current_submission.fields["step_1_field_1"]).to eq("I am a user submission") end end - it "provides class methods to set and list submissions" do - CustomWizard::Wizard.set_submissions(template_json['id'], user, - step_1_field_1: 'I am a user submission' - ) - expect( - CustomWizard::Wizard.submissions(template_json['id'], user) - .first['step_1_field_1'] - ).to eq('I am a user submission') - end - context "class methods" do before do CustomWizard::Template.save(@permitted_template, skip_jobs: true) @@ -273,7 +256,7 @@ describe CustomWizard::Wizard do it "sets wizard redirects if user is permitted" do CustomWizard::Template.save(@permitted_template, skip_jobs: true) - CustomWizard::Wizard.set_wizard_redirect('super_mega_fun_wizard', trusted_user) + CustomWizard::Wizard.set_user_redirect('super_mega_fun_wizard', trusted_user) expect( trusted_user.custom_fields['redirect_to_wizard'] ).to eq("super_mega_fun_wizard") @@ -281,7 +264,7 @@ describe CustomWizard::Wizard do it "does not set a wizard redirect if user is not permitted" do CustomWizard::Template.save(@permitted_template, skip_jobs: true) - CustomWizard::Wizard.set_wizard_redirect('super_mega_fun_wizard', user) + CustomWizard::Wizard.set_user_redirect('super_mega_fun_wizard', user) expect( trusted_user.custom_fields['redirect_to_wizard'] ).to eq(nil) diff --git a/spec/requests/custom_wizard/admin/submissions_controller_spec.rb b/spec/requests/custom_wizard/admin/submissions_controller_spec.rb index f63eead5..eae783aa 100644 --- a/spec/requests/custom_wizard/admin/submissions_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/submissions_controller_spec.rb @@ -5,6 +5,7 @@ describe CustomWizard::AdminSubmissionsController do fab!(:admin_user) { Fabricate(:user, admin: true) } fab!(:user1) { Fabricate(:user) } fab!(:user2) { Fabricate(:user) } + fab!(:user3) { Fabricate(:user) } let(:template) { JSON.parse(File.open( @@ -14,33 +15,35 @@ describe CustomWizard::AdminSubmissionsController do before do CustomWizard::Template.save(template, skip_jobs: true) - CustomWizard::Wizard.set_submissions(template['id'], user1, - step_1_field_1: "I am a user1's submission" - ) - CustomWizard::Wizard.set_submissions(template['id'], user2, - step_1_field_1: "I am a user2's submission" - ) + + template_2 = template.dup + template_2["id"] = "super_mega_fun_wizard_2" + CustomWizard::Template.save(template_2, skip_jobs: true) + + wizard1 = CustomWizard::Wizard.create(template["id"], user1) + wizard2 = CustomWizard::Wizard.create(template["id"], user2) + wizard3 = CustomWizard::Wizard.create(template_2["id"], user3) + + CustomWizard::Submission.new(wizard1, step_1_field_1: "I am a user1's submission").save + CustomWizard::Submission.new(wizard2, step_1_field_1: "I am a user2's submission").save + CustomWizard::Submission.new(wizard3, step_1_field_1: "I am a user3's submission").save + sign_in(admin_user) end - it "returns a basic list of wizards" do + it "returns a list of wizards" do get "/admin/wizards/submissions.json" - expect(response.parsed_body.length).to eq(1) + expect(response.parsed_body.length).to eq(3) expect(response.parsed_body.first['id']).to eq(template['id']) end - it "returns the all user's submissions for a wizard" do + it "returns users' submissions for a wizard" do get "/admin/wizards/submissions/#{template['id']}.json" expect(response.parsed_body['submissions'].length).to eq(2) end - it "returns the all user's submissions for a wizard" do - get "/admin/wizards/submissions/#{template['id']}.json" - expect(response.parsed_body['submissions'].length).to eq(2) - end - - it "downloads all user submissions" do - get "/admin/wizards/submissions/#{template['id']}/download" - expect(response.parsed_body.length).to eq(2) + it "downloads submissions" do + get "/admin/wizards/submissions/#{template_2['id']}/download" + expect(response.parsed_body.length).to eq(1) end end diff --git a/spec/requests/custom_wizard/steps_controller_spec.rb b/spec/requests/custom_wizard/steps_controller_spec.rb index 2424274b..ab705cac 100644 --- a/spec/requests/custom_wizard/steps_controller_spec.rb +++ b/spec/requests/custom_wizard/steps_controller_spec.rb @@ -68,7 +68,7 @@ describe CustomWizard::StepsController do wizard_id = response.parsed_body['wizard']['id'] wizard = CustomWizard::Wizard.create(wizard_id, user) - expect(wizard.submissions.last['step_1_field_1']).to eq("Text input") + expect(wizard.current_submission.fields['step_1_field_1']).to eq("Text input") end context "raises an error" do @@ -175,7 +175,7 @@ describe CustomWizard::StepsController do wizard_id = response.parsed_body['wizard']['id'] wizard = CustomWizard::Wizard.create(wizard_id, user) - group_name = wizard.submissions.last['action_9'] + group_name = wizard.current_submission.fields['action_9'] group = Group.find_by(name: group_name) expect(group.full_name).to eq("My cool group") end @@ -275,7 +275,7 @@ describe CustomWizard::StepsController do wizard_id = response.parsed_body['wizard']['id'] wizard = CustomWizard::Wizard.create(wizard_id, user) - submission = wizard.submissions.last - expect(submission.keys).not_to include("step_2_field_1") + submission = wizard.current_submission + expect(submission.fields.keys).not_to include("step_2_field_1") end end diff --git a/spec/requests/custom_wizard/wizard_controller_spec.rb b/spec/requests/custom_wizard/wizard_controller_spec.rb index 4380bc73..7a977539 100644 --- a/spec/requests/custom_wizard/wizard_controller_spec.rb +++ b/spec/requests/custom_wizard/wizard_controller_spec.rb @@ -71,9 +71,8 @@ describe CustomWizard::WizardController do end it 'skip response contains a redirect_to if in users submissions' do - CustomWizard::Wizard.set_submissions(@template['id'], user, - redirect_to: '/t/2' - ) + @wizard = CustomWizard::Wizard.create(@template["id"], user) + CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission").save put '/w/super-mega-fun-wizard/skip.json' expect(response.parsed_body['redirect_to']).to eq('/t/2') end