diff --git a/config/routes.rb b/config/routes.rb index 110d54c5..28fcbb82 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true CustomWizard::Engine.routes.draw do get ':wizard_id' => 'wizard#index' put ':wizard_id/skip' => 'wizard#skip' @@ -13,21 +14,21 @@ Discourse::Application.routes.append do scope module: 'custom_wizard', constraints: AdminConstraint.new do get 'admin/wizards' => 'admin#index' - + get 'admin/wizards/wizard' => 'admin_wizard#index' get 'admin/wizards/wizard/create' => 'admin#index' get 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#show' put 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#save' delete 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#remove' - + get 'admin/wizards/custom-fields' => 'admin_custom_fields#index' put 'admin/wizards/custom-fields' => 'admin_custom_fields#update' delete 'admin/wizards/custom-fields/:name' => 'admin_custom_fields#destroy' - + get 'admin/wizards/submissions' => 'admin_submissions#index' get 'admin/wizards/submissions/:wizard_id' => 'admin_submissions#show' get 'admin/wizards/submissions/:wizard_id/download' => 'admin_submissions#download' - + get 'admin/wizards/api' => 'admin_api#list' get 'admin/wizards/api/:name' => 'admin_api#find' put 'admin/wizards/api/:name' => 'admin_api#save' @@ -35,12 +36,12 @@ Discourse::Application.routes.append do delete 'admin/wizards/api/:name/logs' => 'admin_api#clearlogs' get 'admin/wizards/api/:name/redirect' => 'admin_api#redirect' get 'admin/wizards/api/:name/authorize' => 'admin_api#authorize' - + get 'admin/wizards/logs' => 'admin_logs#index' - + get 'admin/wizards/manager' => 'admin_manager#index' get 'admin/wizards/manager/export' => 'admin_manager#export' post 'admin/wizards/manager/import' => 'admin_manager#import' delete 'admin/wizards/manager/destroy' => 'admin_manager#destroy' end -end \ No newline at end of file +end diff --git a/controllers/custom_wizard/admin/admin.rb b/controllers/custom_wizard/admin/admin.rb index a2cfb977..8d5e3cad 100644 --- a/controllers/custom_wizard/admin/admin.rb +++ b/controllers/custom_wizard/admin/admin.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true class CustomWizard::AdminController < ::Admin::AdminController before_action :ensure_admin - + def index end - + private - + def find_wizard params.require(:wizard_id) @wizard = CustomWizard::Wizard.create(params[:wizard_id].underscore) raise Discourse::InvalidParameters.new(:wizard_id) unless @wizard end - + def custom_field_list serialize_data(CustomWizard::CustomField.list, CustomWizard::CustomFieldSerializer) end - + def render_error(message) render json: failed_json.merge(error: message) end -end \ No newline at end of file +end diff --git a/controllers/custom_wizard/admin/api.rb b/controllers/custom_wizard/admin/api.rb index b62eb261..a913e9ca 100644 --- a/controllers/custom_wizard/admin/api.rb +++ b/controllers/custom_wizard/admin/api.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::AdminApiController < CustomWizard::AdminController skip_before_action :check_xhr, only: [:redirect] @@ -85,7 +86,7 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController CustomWizard::Api::Authorization.set(params[:name], code: params[:code]) CustomWizard::Api::Authorization.get_token(params[:name]) - return redirect_to path('/admin/wizards/apis/' + params[:name]) + redirect_to path('/admin/wizards/apis/' + params[:name]) end private diff --git a/controllers/custom_wizard/admin/custom_fields.rb b/controllers/custom_wizard/admin/custom_fields.rb index 3cace833..c52759c9 100644 --- a/controllers/custom_wizard/admin/custom_fields.rb +++ b/controllers/custom_wizard/admin/custom_fields.rb @@ -1,26 +1,27 @@ +# frozen_string_literal: true class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController def index render_json_dump(custom_field_list) end - + def update errors = [] field_id = nil field_data = {} - + if saved_field = CustomWizard::CustomField.find(field_params[:id].to_i) CustomWizard::CustomField::ATTRS.each do |attr| field_data[attr] = saved_field.send(attr) end field_id = saved_field.id end - + CustomWizard::CustomField::ATTRS.each do |attr| field_data[attr] = field_params[attr] end - + field = CustomWizard::CustomField.new(field_id, field_data) - + PluginStoreRow.transaction do unless field.save field_errors = field.errors.any? ? @@ -30,26 +31,26 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController raise ActiveRecord::Rollback.new end end - + if errors.any? render json: failed_json.merge(messages: errors) else render json: success_json end end - + def destroy params.require(:name) - + if CustomWizard::CustomField.destroy(params[:name]) render json: success_json else render json: failed_json end end - + private - + def field_params params.required(:custom_field) .permit( @@ -60,4 +61,4 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController serializers: [] ) end -end \ No newline at end of file +end diff --git a/controllers/custom_wizard/admin/logs.rb b/controllers/custom_wizard/admin/logs.rb index 005de8dc..976814f8 100644 --- a/controllers/custom_wizard/admin/logs.rb +++ b/controllers/custom_wizard/admin/logs.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::AdminLogsController < CustomWizard::AdminController def index render_serialized( @@ -5,4 +6,4 @@ class CustomWizard::AdminLogsController < CustomWizard::AdminController CustomWizard::LogSerializer ) end -end \ No newline at end of file +end diff --git a/controllers/custom_wizard/admin/manager.rb b/controllers/custom_wizard/admin/manager.rb index d7fe5ac6..1596c233 100644 --- a/controllers/custom_wizard/admin/manager.rb +++ b/controllers/custom_wizard/admin/manager.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true class CustomWizard::AdminManagerController < CustomWizard::AdminController skip_before_action :check_xhr, only: [:export] before_action :get_wizard_ids, except: [:import] def export templates = [] - + @wizard_ids.each do |wizard_id| if template = CustomWizard::Template.find(wizard_id) templates.push(template) end end - + if templates.empty? return render_error(I18n.t('wizard.export.error.invalid_wizards')) end - + basename = SiteSetting.title.parameterize || 'discourse' - time = Time.now.to_i + time = Time.now.to_i filename = "#{basename}-wizards-#{time}.json" send_data templates.to_json, @@ -27,31 +28,31 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController def import file = File.read(params['file'].tempfile) - + if file.nil? return render_error(I18n.t('wizard.export.error.no_file')) end file_size = file.size max_file_size = 512 * 1024 - + if max_file_size < file_size return render_error(I18n.t('wizard.import.error.file_large')) end - + begin template_json = JSON.parse file rescue JSON::ParserError return render_error(I18n.t('wizard.import.error.invalid_json')) end - + imported = [] failures = [] - + template_json.each do |json| template = CustomWizard::Template.new(json) template.save(skip_jobs: true, create: true) - + if template.errors.any? failures.push( id: json['id'], @@ -70,14 +71,14 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController failures: failures ) end - + def destroy destroyed = [] failures = [] - + @wizard_ids.each do |wizard_id| template = CustomWizard::Template.find(wizard_id) - + if template && CustomWizard::Template.remove(wizard_id) destroyed.push( id: wizard_id, @@ -90,22 +91,22 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController ) end end - + render json: success_json.merge( destroyed: destroyed, failures: failures ) end - + private - + def get_wizard_ids if params['wizard_ids'].blank? return render_error(I18n.t('wizard.export.error.select_one')) end - + wizard_ids = [] - + params['wizard_ids'].each do |wizard_id| begin wizard_ids.push(wizard_id.underscore) @@ -113,11 +114,11 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController # end end - + if wizard_ids.empty? return render_error(I18n.t('wizard.export.error.invalid_wizards')) end - + @wizard_ids = wizard_ids end end diff --git a/controllers/custom_wizard/admin/submissions.rb b/controllers/custom_wizard/admin/submissions.rb index 69088492..5467587e 100644 --- a/controllers/custom_wizard/admin/submissions.rb +++ b/controllers/custom_wizard/admin/submissions.rb @@ -1,45 +1,46 @@ +# frozen_string_literal: true class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController skip_before_action :preload_json, :check_xhr, only: [:download] before_action :find_wizard, except: [:index] - + def index render json: ActiveModel::ArraySerializer.new( CustomWizard::Wizard.list(current_user), each_serializer: CustomWizard::BasicWizardSerializer ) end - + def show render_json_dump( wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false), submissions: build_submissions.as_json ) end - - def download + + def download send_data build_submissions.to_json, filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json", content_type: "application/json", disposition: "attachment" end - + 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 end -end \ No newline at end of file +end diff --git a/controllers/custom_wizard/admin/wizard.rb b/controllers/custom_wizard/admin/wizard.rb index 1bc4ece8..658f6682 100644 --- a/controllers/custom_wizard/admin/wizard.rb +++ b/controllers/custom_wizard/admin/wizard.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true class CustomWizard::AdminWizardController < CustomWizard::AdminController before_action :find_wizard, only: [:show, :remove] - + def index render_json_dump( wizard_list: ActiveModel::ArraySerializer.new( @@ -12,17 +13,17 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController custom_fields: custom_field_list ) end - + def show params.require(:wizard_id) - + if data = CustomWizard::Template.find(params[:wizard_id].underscore) render json: data.as_json else render json: { none: true } end end - + def remove if CustomWizard::Template.remove(@wizard.id) render json: success_json @@ -34,16 +35,16 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController def save template = CustomWizard::Template.new(save_wizard_params.to_h) wizard_id = template.save(create: params[:create]) - + if template.errors.any? render json: failed_json.merge(errors: result.errors.full_messages) - else + else render json: success_json.merge(wizard_id: wizard_id) end end - + private - + def mapped_params [ :type, diff --git a/controllers/custom_wizard/realtime_validations.rb b/controllers/custom_wizard/realtime_validations.rb index 183e7ccd..5a4c71b6 100644 --- a/controllers/custom_wizard/realtime_validations.rb +++ b/controllers/custom_wizard/realtime_validations.rb @@ -6,9 +6,9 @@ class CustomWizard::RealtimeValidationsController < ::ApplicationController result = klass_str.constantize.new(current_user).perform(validation_params) render_serialized(result.items, "#{klass_str}Serializer".constantize, result.serializer_opts) end - + private - + def validation_params params.require(:type) settings = ::CustomWizard::RealtimeValidation.types[params[:type].to_sym] diff --git a/controllers/custom_wizard/steps.rb b/controllers/custom_wizard/steps.rb index c972c0c5..9c6eec47 100644 --- a/controllers/custom_wizard/steps.rb +++ b/controllers/custom_wizard/steps.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::StepsController < ::ApplicationController before_action :ensure_logged_in before_action :ensure_can_update @@ -5,14 +6,14 @@ class CustomWizard::StepsController < ::ApplicationController def update params.require(:step_id) params.require(:wizard_id) - + wizard = @builder.build step = wizard.steps.select { |s| s.id == update_params[:step_id] }.first raise Discourse::InvalidParameters.new(:step_id) if !step - + update = update_params.to_h - + update[:fields] = {} if params[:fields] field_ids = step.fields.map(&:id) @@ -20,15 +21,15 @@ class CustomWizard::StepsController < ::ApplicationController update[:fields][k] = v if field_ids.include? k end end - + updater = wizard.create_updater(update[:step_id], update[:fields]) updater.update - + if updater.success? result = success_json result.merge!(updater.result) if updater.result result[:refresh_required] = true if updater.refresh_required? - + render json: result else errors = [] @@ -38,24 +39,24 @@ class CustomWizard::StepsController < ::ApplicationController render json: { errors: errors }, status: 422 end end - + private - + def ensure_can_update @builder = CustomWizard::Builder.new( update_params[:wizard_id].underscore, current_user ) - + if @builder.nil? raise Discourse::InvalidParameters.new(:wizard_id) end - + if !@builder.wizard || !@builder.wizard.can_access? raise Discourse::InvalidAccess.new end end - + def update_params params.permit(:wizard_id, :step_id) end diff --git a/controllers/custom_wizard/wizard.rb b/controllers/custom_wizard/wizard.rb index 0cc46037..38b16d3e 100644 --- a/controllers/custom_wizard/wizard.rb +++ b/controllers/custom_wizard/wizard.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true class CustomWizard::WizardController < ::ApplicationController prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'views')) layout 'wizard' - + before_action :ensure_plugin_enabled helper_method :wizard_page_title helper_method :wizard_theme_ids @@ -22,12 +23,12 @@ class CustomWizard::WizardController < ::ApplicationController respond_to do |format| format.json do builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user) - + if builder.wizard.present? builder_opts = {} builder_opts[:reset] = params[:reset] built_wizard = builder.build(builder_opts, params) - + render_serialized(built_wizard, ::CustomWizard::WizardSerializer, root: false) else render json: { error: I18n.t('wizard.none') } @@ -39,14 +40,14 @@ class CustomWizard::WizardController < ::ApplicationController def skip params.require(:wizard_id) - + if wizard.required && !wizard.completed? && wizard.permitted? return render json: { error: I18n.t('wizard.no_skip') } end result = success_json user = current_user - + if user submission = wizard.current_submission if submission && submission['redirect_to'] @@ -61,9 +62,9 @@ class CustomWizard::WizardController < ::ApplicationController render json: result end - + private - + def ensure_plugin_enabled unless SiteSetting.custom_wizard_enabled redirect_to path("/") diff --git a/db/migrate/20200718014105_update_watch_categories_action.rb b/db/migrate/20200718014105_update_watch_categories_action.rb index bf24004d..481eaeb7 100644 --- a/db/migrate/20200718014105_update_watch_categories_action.rb +++ b/db/migrate/20200718014105_update_watch_categories_action.rb @@ -1,27 +1,28 @@ +# frozen_string_literal: true class UpdateWatchCategoriesAction < ActiveRecord::Migration[6.0] def change watch_category_wizards = PluginStoreRow.where(" plugin_name = 'custom_wizard' AND value::jsonb -> 'actions' @> '[{ \"type\" : \"watch_categories\" }]'::jsonb ") - + if watch_category_wizards.exists? watch_category_wizards.each do |row| begin wizard_json = JSON.parse(row.value) rescue TypeError, JSON::ParserError next - end - + end + wizard_json['actions'].each do |a| if a['type'] === "watch_categories" && a['wizard_user'] == nil a['wizard_user'] = true end end - + row.value = wizard_json.to_json row.save end end end -end \ No newline at end of file +end diff --git a/extensions/custom_field/preloader.rb b/extensions/custom_field/preloader.rb index ff3a8d61..c510d292 100644 --- a/extensions/custom_field/preloader.rb +++ b/extensions/custom_field/preloader.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module CustomWizardCustomFieldPreloader def preload_custom_fields(objects, fields) if objects.present? && cw_fields_enabled? @@ -10,12 +11,12 @@ module CustomWizardCustomFieldPreloader end super(objects, fields) end - + def cw_fields_enabled? SiteSetting.custom_wizard_enabled && CustomWizard::CustomField.enabled? end - + def cw_fields CustomWizard::CustomField.list_by(:klass, @cw_klass) end -end \ No newline at end of file +end diff --git a/extensions/custom_field/serializer.rb b/extensions/custom_field/serializer.rb index 75f140d4..2a5e7da3 100644 --- a/extensions/custom_field/serializer.rb +++ b/extensions/custom_field/serializer.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true module CustomWizardCustomFieldSerializer def attributes(*args) hash = super - + if cw_fields_enabled? @cw_klass = get_cw_class - + if cw_fields.any? cw_fields.each do |field| if @cw_klass == "topic_view" @@ -15,12 +16,12 @@ module CustomWizardCustomFieldSerializer end end end - + hash end - + private - + def cw_fields_enabled? SiteSetting.custom_wizard_enabled && CustomWizard::CustomField.enabled? end @@ -28,7 +29,7 @@ module CustomWizardCustomFieldSerializer def cw_fields CustomWizard::CustomField.list_by(:serializers, @cw_klass) end - + def get_cw_class self.class.ancestors.map do |klass| klass.to_s.underscore.gsub("_serializer", "") @@ -36,4 +37,4 @@ module CustomWizardCustomFieldSerializer CustomWizard::CustomField.serializers.include?(klass) end.first end -end \ No newline at end of file +end diff --git a/extensions/extra_locales_controller.rb b/extensions/extra_locales_controller.rb index 110f30d1..e7c5a02e 100644 --- a/extensions/extra_locales_controller.rb +++ b/extensions/extra_locales_controller.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true module ExtraLocalesControllerCustomWizard private def valid_bundle?(bundle) super || begin return false unless bundle =~ /wizard/ && request.referer =~ /\/w\// path = URI(request.referer).path wizard_id = path.split('/w/').last - CustomWizard::Template.exists?(wizard_id.underscore) + CustomWizard::Template.exists?(wizard_id.underscore) end end -end \ No newline at end of file +end diff --git a/extensions/invites_controller.rb b/extensions/invites_controller.rb index caa3a976..cafb15bd 100644 --- a/extensions/invites_controller.rb +++ b/extensions/invites_controller.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module InvitesControllerCustomWizard def path(url) if ::Wizard.user_requires_completion?(@user) @@ -15,4 +16,4 @@ module InvitesControllerCustomWizard super @user = user end -end \ No newline at end of file +end diff --git a/extensions/users_controller.rb b/extensions/users_controller.rb index 71e62293..e2dc464f 100644 --- a/extensions/users_controller.rb +++ b/extensions/users_controller.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module CustomWizardUsersController def account_created if current_user.present? && @@ -6,4 +7,4 @@ module CustomWizardUsersController end super end -end \ No newline at end of file +end diff --git a/extensions/wizard_field.rb b/extensions/wizard_field.rb index e62f5d9a..2042872f 100644 --- a/extensions/wizard_field.rb +++ b/extensions/wizard_field.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module CustomWizardFieldExtension attr_reader :raw, :label, @@ -14,7 +15,7 @@ module CustomWizardFieldExtension :property, :content, :number - + def initialize(attrs) super @raw = attrs || {} @@ -36,4 +37,4 @@ module CustomWizardFieldExtension def label @label ||= PrettyText.cook(@raw[:label]) end -end \ No newline at end of file +end diff --git a/extensions/wizard_step.rb b/extensions/wizard_step.rb index b8af28ae..4ae0224c 100644 --- a/extensions/wizard_step.rb +++ b/extensions/wizard_step.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module CustomWizardStepExtension attr_accessor :title, :description, :key, :permitted, :permitted_message -end \ No newline at end of file +end diff --git a/jobs/clear_after_time_wizard.rb b/jobs/clear_after_time_wizard.rb index 50443691..37d997db 100644 --- a/jobs/clear_after_time_wizard.rb +++ b/jobs/clear_after_time_wizard.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module Jobs class ClearAfterTimeWizard < ::Jobs::Base sidekiq_options queue: 'critical' diff --git a/jobs/refresh_api_access_token.rb b/jobs/refresh_api_access_token.rb index 114c39d1..05ef3655 100644 --- a/jobs/refresh_api_access_token.rb +++ b/jobs/refresh_api_access_token.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module Jobs class RefreshApiAccessToken < ::Jobs::Base def execute(args) diff --git a/jobs/set_after_time_wizard.rb b/jobs/set_after_time_wizard.rb index 38d0eebe..3b2e9e11 100644 --- a/jobs/set_after_time_wizard.rb +++ b/jobs/set_after_time_wizard.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true module Jobs class SetAfterTimeWizard < ::Jobs::Base def execute(args) if SiteSetting.custom_wizard_enabled wizard = CustomWizard::Wizard.create(args[:wizard_id]) - + if wizard && wizard.after_time user_ids = [] diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index eb97f0f9..fbfa17a5 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true class CustomWizard::Action attr_accessor :data, :action, :user, :guardian, :result - + def initialize(params) @wizard = params[:wizard] @action = params[:action] @@ -14,41 +15,41 @@ class CustomWizard::Action @log = [] @result = CustomWizard::ActionResult.new end - - def perform + + def perform ActiveRecord::Base.transaction do self.send(action['type'].to_sym) end - + if creates_post? && @result.success? @result.handler.enqueue_jobs end - + if @result.success? && @result.output.present? data[action['id']] = @result.output end - + save_log end - + def mapper @mapper ||= CustomWizard::Mapper.new(user: user, data: data) end - + def create_topic params = basic_topic_params.merge(public_topic_params) - + if params[:title].present? && params[:raw].present? creator = PostCreator.new(user, params) post = creator.create - + if creator.errors.present? messages = creator.errors.full_messages.join(" ") log_error("failed to create", messages) elsif action['skip_redirect'].blank? data['redirect_on_complete'] = post.topic.url end - + if creator.errors.blank? log_success("created topic", "id: #{post.topic.id}") result.handler = creator @@ -58,7 +59,7 @@ class CustomWizard::Action log_error("invalid topic params", "title: #{params[:title]}; post: #{params[:raw]}") end end - + def send_message if action['required'].present? @@ -67,27 +68,27 @@ class CustomWizard::Action data: data, user: user ).perform - + if required.blank? log_error("required input not present") return end end - + params = basic_topic_params - + targets = CustomWizard::Mapper.new( inputs: action['recipient'], data: data, user: user, multiple: true ).perform - + if targets.blank? log_error("no recipients", "send_message has no recipients") return end - + targets.each do |target| if Group.find_by(name: target) params[:target_group_names] = target @@ -97,14 +98,14 @@ class CustomWizard::Action # end end - + if params[:title].present? && params[:raw].present? && (params[:target_usernames].present? || params[:target_group_names].present?) - + params[:archetype] = Archetype.private_message - + creator = PostCreator.new(user, params) post = creator.create @@ -114,7 +115,7 @@ class CustomWizard::Action elsif action['skip_redirect'].blank? data['redirect_on_complete'] = post.topic.url end - + if creator.errors.blank? log_success("created message", "id: #{post.topic.id}") result.handler = creator @@ -130,7 +131,7 @@ class CustomWizard::Action def update_profile params = {} - + if (profile_updates = action['profile_updates']) profile_updates.first[:pairs].each do |pair| if allowed_profile_field?(pair['key']) @@ -142,7 +143,7 @@ class CustomWizard::Action ), pair['key'] ) - + if user_field?(pair['key']) params[:custom_fields] ||= {} params[:custom_fields][key] = value @@ -152,16 +153,16 @@ class CustomWizard::Action end end end - + params = add_custom_fields(params) - + if params.present? result = UserUpdater.new(Discourse.system_user, user).update(params) - + if params[:avatar].present? result = update_avatar(params[:avatar]) end - + if result log_success("updated profile fields", "fields: #{params.keys.map(&:to_s).join(',')}") else @@ -178,7 +179,7 @@ class CustomWizard::Action data: data, user: user ).perform - + watched_categories = [*watched_categories].map(&:to_i) notification_level = action['notification_level'] @@ -193,23 +194,23 @@ class CustomWizard::Action data: data, user: user ).perform - + users = [] - + if action['usernames'] mapped_users = CustomWizard::Mapper.new( inputs: action['usernames'], data: data, user: user ).perform - + if mapped_users.present? mapped_users = mapped_users.split(',') .map { |username| User.find_by(username: username) } users.push(*mapped_users) end end - + if ActiveRecord::Type::Boolean.new.cast(action['wizard_user']) users.push(user) end @@ -217,26 +218,26 @@ class CustomWizard::Action category_ids = Category.all.pluck(:id) set_level = CategoryUser.notification_levels[notification_level.to_sym] mute_level = CategoryUser.notification_levels[:muted] - + users.each do |user| category_ids.each do |category_id| new_level = nil - + if watched_categories.include?(category_id) && set_level != nil new_level = set_level elsif mute_remainder new_level = mute_level end - + if new_level CategoryUser.set_notification_level_for_category(user, new_level, category_id) end end - + if watched_categories.any? log_success("#{user.username} notifications for #{watched_categories} set to #{set_level}") end - + if mute_remainder log_success("#{user.username} notifications for all other categories muted") end @@ -264,29 +265,29 @@ class CustomWizard::Action log_success("api request succeeded", "result: #{result}") end end - + def open_composer params = basic_topic_params - + if params[:title].present? && params[:raw].present? url = "/new-topic?title=#{encode_query_param(params[:title])}" url += "&body=#{encode_query_param(params[:raw])}" - + if category_id = action_category url += "&category_id=#{category_id}" end - + if tags = action_tags url += "&tags=#{tags.join(',')}" end - + route_to = Discourse.base_uri + url @result.output = data['route_to'] = route_to - + log_success("route: #{route_to}") else log_error("invalid composer params", "title: #{params[:title]}; post: #{params[:raw]}") - end + end end def add_to_group @@ -298,14 +299,14 @@ class CustomWizard::Action multiple: true } ).perform - + group_map = group_map.flatten.compact - + unless group_map.present? log_error("invalid group map") return end - + groups = group_map.reduce([]) do |groups, g| begin groups.push(Integer(g)) @@ -313,30 +314,30 @@ class CustomWizard::Action group = Group.find_by(name: g) groups.push(group.id) if group end - + groups end - + result = nil - + if groups.present? groups.each do |group_id| group = Group.find(group_id) if group_id result = group.add(user) if group end end - + if result log_success("added to groups", "groups: #{groups.map(&:to_s).join(',')}") else - detail = groups.present? ? "groups: #{groups.map(&:to_s).join(',')}" : nil + detail = groups.present? ? "groups: #{groups.map(&:to_s).join(',')}" : nil log_error("failed to add to groups", detail) end end def route_to return unless (url_input = action['url']).present? - + if url_input.is_a?(String) url = mapper.interpolate(url_input) else @@ -346,18 +347,18 @@ class CustomWizard::Action user: user ).perform end - + if action['code'] data[action['code']] = SecureRandom.hex(8) url += "&#{action['code']}=#{data[action['code']]}" end - + route_to = UrlHelper.encode(url) data['route_to'] = route_to - + log_info("route: #{route_to}") end - + def create_group group = begin @@ -365,12 +366,12 @@ class CustomWizard::Action rescue ArgumentError => e raise Discourse::InvalidParameters, "Invalid group params" end - + if group.save def get_user_ids(username_string) User.where(username: username_string.split(",")).pluck(:id) end - + if new_group_params[:owner_usernames].present? owner_ids = get_user_ids(new_group_params[:owner_usernames]) owner_ids.each { |user_id| group.group_users.build(user_id: user_id, owner: true) } @@ -381,24 +382,24 @@ class CustomWizard::Action user_ids -= owner_ids if owner_ids user_ids.each { |user_id| group.group_users.build(user_id: user_id) } end - + GroupActionLogger.new(user, group, skip_guardian: true).log_change_group_settings log_success("Group created", group.name) - + result.output = group.name else log_error("Group creation failed", group.errors.messages) end end - - def create_category + + def create_category category = begin Category.new(new_category_params.merge(user: user)) rescue ArgumentError => e raise Discourse::InvalidParameters, "Invalid category params" end - + if category.save StaffActionLogger.new(user).log_category_creation(category) log_success("Category created", category.name) @@ -407,18 +408,18 @@ class CustomWizard::Action log_error("Category creation failed", category.errors.messages) end end - + private - + def action_category output = CustomWizard::Mapper.new( inputs: action['category'], data: data, user: user ).perform - + return false unless output.present? - + if output.is_a?(Array) output.first elsif output.is_a?(Integer) @@ -427,23 +428,23 @@ class CustomWizard::Action output.to_i end end - + def action_tags output = CustomWizard::Mapper.new( inputs: action['tags'], data: data, user: user, ).perform - + return false unless output.present? - + if output.is_a?(Array) output.flatten else output.is_a?(String) [*output] end end - + def add_custom_fields(params = {}) if (custom_fields = action['custom_fields']).present? field_map = CustomWizard::Mapper.new( @@ -451,26 +452,25 @@ class CustomWizard::Action data: data, user: user ).perform - + registered_fields = CustomWizard::CustomField.cached_list - + field_map.each do |field| keyArr = field[:key].split('.') value = field[:value] - + if keyArr.length > 1 klass = keyArr.first name = keyArr.last else name = keyArr.first end - - + registered = registered_fields.select { |f| f[:name] == name } if registered.first.present? klass = registered.first[:klass] end - + if klass === 'topic' params[:topic_opts] ||= {} params[:topic_opts][:custom_fields] ||= {} @@ -481,15 +481,15 @@ class CustomWizard::Action end end end - + params end - + def basic_topic_params params = { skip_validations: true } - + params[:title] = CustomWizard::Mapper.new( inputs: action['title'], data: data, @@ -499,23 +499,23 @@ class CustomWizard::Action params[:raw] = action['post_builder'] ? mapper.interpolate(action['post_template']) : data[action['post']] - + params[:import_mode] = ActiveRecord::Type::Boolean.new.cast(action['suppress_notifications']) - + add_custom_fields(params) end - + def public_topic_params params = {} - + if category = action_category params[:category] = category end - + if tags = action_tags params[:tags] = tags end - + if public_topic_fields.any? public_topic_fields.each do |field| unless action[field].nil? || action[field] == "" @@ -527,13 +527,13 @@ class CustomWizard::Action end end end - + params end - + def new_group_params params = {} - + %w( name full_name @@ -548,37 +548,37 @@ class CustomWizard::Action grant_trust_level ).each do |attr| input = action[attr] - + if attr === "name" && input.blank? raise ArgumentError.new end - + if attr === "full_name" && input.blank? input = action["name"] end - - if input.present? + + if input.present? value = CustomWizard::Mapper.new( inputs: input, data: data, user: user ).perform - + if value value = value.parameterize(separator: '_') if attr === "name" value = value.to_i if attr.include?("_level") - + params[attr.to_sym] = value end end end - + add_custom_fields(params) end - + def new_category_params params = {} - + %w( name slug @@ -587,61 +587,61 @@ class CustomWizard::Action parent_category_id permissions ).each do |attr| - if action[attr].present? + if action[attr].present? value = CustomWizard::Mapper.new( inputs: action[attr], data: data, user: user ).perform - + if value if attr === "parent_category_id" && value.is_a?(Array) value = value[0] end - + if attr === "permissions" && value.is_a?(Array) permissions = value value = {} - + permissions.each do |p| k = p[:key] v = p[:value].to_i - + if k.is_a?(Array) group = Group.find_by(id: k[0]) k = group.name else k = k.parameterize(separator: '_') end - - value[k] = v + + value[k] = v end end - + if attr === 'slug' value = value.parameterize(separator: '-') end - + params[attr.to_sym] = value end end end - + add_custom_fields(params) end - + def creates_post? [:create_topic, :send_message].include?(action['type'].to_sym) end - + def public_topic_fields ['visible'] end - + def profile_url_fields ['profile_background', 'card_background'] end - + def cast_profile_key(key) if profile_url_fields.include?(key) "#{key}_upload_url" @@ -649,10 +649,10 @@ class CustomWizard::Action key end end - + def cast_profile_value(value, key) return value if value.nil? - + if profile_url_fields.include?(key) value['url'] elsif key === 'avatar' @@ -661,26 +661,26 @@ class CustomWizard::Action value end end - + def profile_excluded_fields ['username', 'email', 'trust_level'].freeze end - + def allowed_profile_field?(field) allowed_profile_fields.include?(field) || user_field?(field) end - + def user_field?(field) field.to_s.include?(::User::USER_FIELD_PREFIX) && - ::UserField.exists?(field.split('_').last.to_i) + ::UserField.exists?(field.split('_').last.to_i) end - + def allowed_profile_fields - CustomWizard::Mapper.user_fields.select { |f| profile_excluded_fields.exclude?(f) } + - profile_url_fields + + CustomWizard::Mapper.user_fields.select { |f| profile_excluded_fields.exclude?(f) } + + profile_url_fields + ['avatar'] end - + def update_avatar(upload_id) user.create_user_avatar unless user.user_avatar user.user_avatar.custom_upload_id = upload_id @@ -688,34 +688,34 @@ class CustomWizard::Action user.save! user.user_avatar.save! end - + def encode_query_param(param) Addressable::URI.encode_component(param, Addressable::URI::CharacterClasses::UNRESERVED) end - + def log_success(message, detail = nil) @log.push("success: #{message} - #{detail}") @result.success = true end - + def log_error(message, detail = nil) @log.push("error: #{message} - #{detail}") @result.success = false end - + def log_info(message, detail = nil) @log.push("info: #{message} - #{detail}") end - + def save_log log = "wizard: #{@wizard.id}; action: #{action['type']}; user: #{user.username}" - + if @log.any? @log.each do |item| - log << "; #{item.to_s}" + log += "; #{item.to_s}" end end - + CustomWizard::Log.create(log) end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/action_result.rb b/lib/custom_wizard/action_result.rb index 80f2b55d..07c81284 100644 --- a/lib/custom_wizard/action_result.rb +++ b/lib/custom_wizard/action_result.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::ActionResult attr_accessor :success, :handler, :output diff --git a/lib/custom_wizard/api/api.rb b/lib/custom_wizard/api/api.rb index a5d4c155..0c2284b4 100644 --- a/lib/custom_wizard/api/api.rb +++ b/lib/custom_wizard/api/api.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true class CustomWizard::Api include ActiveModel::SerializerSupport attr_accessor :name, :title - def initialize(name, data={}) + def initialize(name, data = {}) @name = name data.each do |k, v| self.send "#{k}=", v if self.respond_to?(k) diff --git a/lib/custom_wizard/api/authorization.rb b/lib/custom_wizard/api/authorization.rb index 1bfa4a29..7355a941 100644 --- a/lib/custom_wizard/api/authorization.rb +++ b/lib/custom_wizard/api/authorization.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'excon' class CustomWizard::Api::Authorization @@ -19,7 +20,7 @@ class CustomWizard::Api::Authorization :username, :password - def initialize(api_name, data={}) + def initialize(api_name, data = {}) @api_name = api_name data.each do |k, v| @@ -106,18 +107,18 @@ class CustomWizard::Api::Authorization connection = Excon.new( authorization.token_url, - :headers => { + headers: { "Content-Type" => "application/x-www-form-urlencoded" }, - :method => 'GET', - :query => URI.encode_www_form(body) + method: 'GET', + query: URI.encode_www_form(body) ) begin result = connection.request() - log_params = {time: Time.now, user_id: 0, status: 'SUCCESS', url: authorization.token_url, error: ""} + log_params = { time: Time.now, user_id: 0, status: 'SUCCESS', url: authorization.token_url, error: "" } CustomWizard::Api::LogEntry.set(name, log_params) rescue SystemCallError => e - log_params = {time: Time.now, user_id: 0, status: 'FAILURE', url: authorization.token_url, error: "Token refresh request failed: #{e.inspect}"} + log_params = { time: Time.now, user_id: 0, status: 'FAILURE', url: authorization.token_url, error: "Token refresh request failed: #{e.inspect}" } CustomWizard::Api::LogEntry.set(name, log_params) end diff --git a/lib/custom_wizard/api/endpoint.rb b/lib/custom_wizard/api/endpoint.rb index f77a49e6..71af3453 100644 --- a/lib/custom_wizard/api/endpoint.rb +++ b/lib/custom_wizard/api/endpoint.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Api::Endpoint include ActiveModel::SerializerSupport @@ -9,7 +10,7 @@ class CustomWizard::Api::Endpoint :content_type, :success_codes - def initialize(api_name, data={}) + def initialize(api_name, data = {}) @api_name = api_name data.each do |k, v| @@ -35,7 +36,7 @@ class CustomWizard::Api::Endpoint self.get(api_name, endpoint_id) end - def self.get(api_name, endpoint_id, opts={}) + def self.get(api_name, endpoint_id, opts = {}) return nil if !endpoint_id if data = PluginStore.get("custom_wizard_api_#{api_name}", "endpoint_#{endpoint_id}") @@ -68,7 +69,7 @@ class CustomWizard::Api::Endpoint endpoint = self.get(api_name, endpoint_id) auth_string = CustomWizard::Api::Authorization.authorization_string(api_name) content_type = endpoint.content_type - + headers = {} headers["Authorization"] = auth_string if auth_string headers["Content-Type"] = content_type if content_type @@ -82,13 +83,13 @@ class CustomWizard::Api::Endpoint body = JSON.generate(body) elsif content_type === "application/x-www-form-urlencoded" body = URI.encode_www_form(body) - end - + end + params[:body] = body end response = connection.request(params) - + if endpoint.success_codes.include?(response.status) begin result = JSON.parse(response.body) @@ -97,7 +98,7 @@ class CustomWizard::Api::Endpoint end CustomWizard::Api::LogEntry.set(api_name, log_params(user, 'SUCCESS', endpoint.url)) - + result else message = "API request failed" @@ -105,7 +106,7 @@ class CustomWizard::Api::Endpoint { error: message } end end - + def self.log_params(user, status, url, message = "") { time: Time.now, user_id: user.id, status: status, url: url, error: message } end diff --git a/lib/custom_wizard/api/log_entry.rb b/lib/custom_wizard/api/log_entry.rb index 1408615d..3fe2969e 100644 --- a/lib/custom_wizard/api/log_entry.rb +++ b/lib/custom_wizard/api/log_entry.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Api::LogEntry include ActiveModel::SerializerSupport @@ -12,7 +13,7 @@ class CustomWizard::Api::LogEntry :name, :avatar_template - def initialize(api_name, data={}) + def initialize(api_name, data = {}) @api_name = api_name data.each do |k, v| @@ -38,7 +39,7 @@ class CustomWizard::Api::LogEntry self.get(api_name, log_id) end - def self.get(api_name, log_id, opts={}) + def self.get(api_name, log_id, opts = {}) return nil if !log_id if data = PluginStore.get("custom_wizard_api_#{api_name}", "log_#{log_id}") diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb index ee8adc4b..9a2d1060 100644 --- a/lib/custom_wizard/builder.rb +++ b/lib/custom_wizard/builder.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true class CustomWizard::Builder attr_accessor :wizard, :updater, :submissions - def initialize(wizard_id, user=nil) + def initialize(wizard_id, user = nil) template = CustomWizard::Template.find(wizard_id) return nil if template.blank? - + @wizard = CustomWizard::Wizard.new(template, user) @steps = template['steps'] || [] @actions = template['actions'] || [] @@ -23,7 +24,7 @@ class CustomWizard::Builder sorted_handlers << { priority: priority, wizard_id: wizard_id, block: block } @sorted_handlers.sort_by! { |h| -h[:priority] } end - + def mapper CustomWizard::Mapper.new( user: @wizard.user, @@ -34,36 +35,36 @@ class CustomWizard::Builder def build(build_opts = {}, params = {}) return nil if !SiteSetting.custom_wizard_enabled || !@wizard return @wizard if !@wizard.can_access? - + build_opts[:reset] = build_opts[:reset] || @wizard.restart_on_revisit @steps.each do |step_template| @wizard.append_step(step_template['id']) do |step| step.permitted = true - + if step_template['required_data'] step = ensure_required_data(step, step_template) end - + if !step.permitted if step_template['required_data_message'] - step.permitted_message = step_template['required_data_message'] + step.permitted_message = step_template['required_data_message'] end next end - + step.title = step_template['title'] if step_template['title'] step.banner = step_template['banner'] if step_template['banner'] step.key = step_template['key'] if step_template['key'] - + if step_template['description'] step.description = mapper.interpolate( step_template['description'], user: true, value: true - ) + ) end - + if permitted_params = step_template['permitted_params'] save_permitted_params(permitted_params, params) end @@ -77,9 +78,9 @@ class CustomWizard::Builder step.on_update do |updater| @updater = updater user = @wizard.user - + updater.validate - + next if updater.errors.any? CustomWizard::Builder.step_handlers.each do |handler| @@ -95,15 +96,15 @@ class CustomWizard::Builder if current_submission = @wizard.current_submission submission = current_submission.merge(submission) end - + final_step = updater.step.next.nil? - + if @actions.present? @actions.each do |action| - + if (action['run_after'] === updater.step.id) || (final_step && (!action['run_after'] || (action['run_after'] === 'wizard_completion'))) - + CustomWizard::Action.new( wizard: @wizard, action: action, @@ -113,28 +114,28 @@ class CustomWizard::Builder end end end - + if updater.errors.empty? if route_to = submission['route_to'] submission.delete('route_to') end - + if @wizard.save_submissions save_submissions(submission, final_step) end - + if final_step if @wizard.id == @wizard.user.custom_fields['redirect_to_wizard'] - @wizard.user.custom_fields.delete('redirect_to_wizard'); + @wizard.user.custom_fields.delete('redirect_to_wizard') @wizard.user.save_custom_fields(true) end - + redirect_url = route_to || submission['redirect_on_complete'] || submission["redirect_to"] updater.result[:redirect_on_complete] = redirect_url elsif route_to updater.result[:redirect_on_next] = route_to end - + true else false @@ -142,7 +143,7 @@ class CustomWizard::Builder end end end - + @wizard end @@ -153,7 +154,7 @@ class CustomWizard::Builder required: field_template['required'], number: index + 1 } - + params[:label] = field_template['label'] if field_template['label'] params[:description] = field_template['description'] if field_template['description'] params[:image] = field_template['image'] if field_template['image'] @@ -163,11 +164,11 @@ class CustomWizard::Builder params[:max_length] = field_template['max_length'] if field_template['max_length'] params[:char_counter] = field_template['char_counter'] if field_template['char_counter'] 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']] end - + if field_template['type'] === 'group' && params[:value].present? params[:value] = params[:value].first end @@ -179,19 +180,19 @@ class CustomWizard::Builder if field_template['type'] === 'upload' params[:file_types] = field_template['file_types'] end - + if ['date', 'time', 'date_time'].include?(field_template['type']) params[:format] = field_template['format'] end - + if field_template['type'] === 'category' || field_template['type'] === 'tag' params[:limit] = field_template['limit'] end - + if field_template['type'] === 'category' params[:property] = field_template['property'] end - + if field_template['type'] === 'category' || ( field_template['validations'] && field_template['validations']['similar_topics'] && @@ -199,11 +200,11 @@ class CustomWizard::Builder ) @wizard.needs_categories = true end - + if field_template['type'] === 'group' @wizard.needs_groups = true end - + if (content_inputs = field_template['content']).present? content = CustomWizard::Mapper.new( inputs: content_inputs, @@ -213,35 +214,35 @@ class CustomWizard::Builder with_type: true } ).perform - + if content.present? && content[:result].present? - + if content[:type] == 'association' content[:result] = content[:result].map do |item| - { + { id: item[:key], - name: item[:value] + name: item[:value] } end end - + if content[:type] == 'assignment' && field_template['type'] === 'dropdown' content[:result] = content[:result].map do |item| - { + { id: item, name: item } end end - + params[:content] = content[:result] end end - + field = step.add_field(params) end - + def prefill_field(field_template, step_template) if (prefill = field_template['prefill']).present? CustomWizard::Mapper.new( @@ -267,7 +268,7 @@ class CustomWizard::Builder @wizard.set_submissions(@submissions) end end - + def save_permitted_params(permitted_params, params) permitted_data = {} @@ -283,28 +284,28 @@ class CustomWizard::Builder save_submissions(current_data.merge(permitted_data), false) end end - + def ensure_required_data(step, step_template) step_template['required_data'].each do |required| pairs = required['pairs'].select do |pair| pair['key'].present? && pair['value'].present? end - + if pairs.any? && !@submissions.last step.permitted = false break end - - pairs.each do |pair| + + pairs.each do |pair| pair['key'] = @submissions.last[pair['key']] end - + if !mapper.validate_pairs(pairs) step.permitted = false break end end - + step end end diff --git a/lib/custom_wizard/cache.rb b/lib/custom_wizard/cache.rb index dea98e00..39673ab6 100644 --- a/lib/custom_wizard/cache.rb +++ b/lib/custom_wizard/cache.rb @@ -4,30 +4,30 @@ class ::CustomWizard::Cache def initialize(key) @key = "#{CustomWizard::PLUGIN_NAME}_#{key}" end - + def read cache.read(@key) end - + def write(data) synchronize { cache.write(@key, data) } end - + def delete synchronize { cache.delete(@key) } end - + def synchronize DistributedMutex.synchronize(@key) { yield } end - + def cache @cache ||= Discourse.cache end - + def self.wrap(key, &block) c = new(key) - + if cached = c.read cached else @@ -36,4 +36,4 @@ class ::CustomWizard::Cache result end end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index 0f806bbc..e3f01a1a 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -3,14 +3,14 @@ class ::CustomWizard::CustomField include HasErrors include ActiveModel::Serialization - + attr_reader :id - + ATTRS ||= ["name", "klass", "type", "serializers"] REQUIRED ||= ["name", "klass", "type"] NAMESPACE ||= "custom_wizard_custom_fields" NAME_MIN_LENGTH ||= 3 - + CLASSES ||= { topic: ["topic_view", "topic_list_item"], group: ["basic_group"], @@ -19,20 +19,20 @@ class ::CustomWizard::CustomField } TYPES ||= ["string", "boolean", "integer", "json"] LIST_CACHE_KEY ||= 'custom_field_list' - + def self.serializers CLASSES.values.flatten.uniq end - + def initialize(id, data) @id = id data = data.with_indifferent_access - + ATTRS.each do |attr| self.class.class_eval { attr_accessor attr } - + value = data[attr] - + if value.present? send("#{attr}=", value) end @@ -45,11 +45,11 @@ class ::CustomWizard::CustomField if valid? data = {} key = name - + (ATTRS - ['name']).each do |attr| data[attr] = send(attr) end - + if self.class.save_to_store(id, key, data) self.class.invalidate_cache true @@ -60,50 +60,49 @@ class ::CustomWizard::CustomField false end end - + def validate ATTRS.each do |attr| value = send(attr) i18n_key = "wizard.custom_field.error" - + if value.blank? if REQUIRED.include?(attr) add_error(I18n.t("#{i18n_key}.required_attribute", attr: attr)) end next end - + if (attr == 'klass' && CLASSES.keys.exclude?(value.to_sym)) || (attr == 'serializers' && CLASSES[klass.to_sym].blank?) add_error(I18n.t("#{i18n_key}.unsupported_class", class: value)) next end - + if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0 add_error(I18n.t("#{i18n_key}.unsupported_serializers", class: klass, serializers: unsupported.join(", ") )) end - + if attr == 'type' && TYPES.exclude?(value) add_error(I18n.t("#{i18n_key}.unsupported_type", type: value)) end - - + if attr == 'name' unless value.is_a?(String) add_error(I18n.t("#{i18n_key}.name_invalid", name: value)) end - + if value.length < NAME_MIN_LENGTH add_error(I18n.t("#{i18n_key}.name_too_short", name: value, min_length: NAME_MIN_LENGTH)) end - + if new? && self.class.exists?(name) add_error(I18n.t("#{i18n_key}.name_already_taken", name: value)) end - + begin @name = value.parameterize(separator: '_') rescue @@ -112,21 +111,21 @@ class ::CustomWizard::CustomField end end end - + def new? id.blank? end - + def valid? errors.blank? end - + def self.list PluginStoreRow.where(plugin_name: NAMESPACE).map do |record| create_from_store(record) end end - + def self.cached_list ::CustomWizard::Cache.wrap(LIST_CACHE_KEY) do PluginStoreRow.where(plugin_name: NAMESPACE).map do |record| @@ -134,11 +133,11 @@ class ::CustomWizard::CustomField end end end - + def self.list_by(attr, value, cached: true) attr = attr.to_sym fields = cached ? cached_list : list - + fields.select do |cf| if attr == :serializers cf[attr].include?(value) @@ -147,38 +146,38 @@ class ::CustomWizard::CustomField end end end - + def self.exists?(name) PluginStoreRow.where(plugin_name: NAMESPACE, key: name).exists? end - + def self.find(field_id) record = PluginStoreRow.find_by(id: field_id, plugin_name: NAMESPACE) - + if record create_from_store(record) else false end end - + def self.find_by_name(name) record = PluginStoreRow.find_by(key: name, plugin_name: NAMESPACE) - + if record create_from_store(record) else false end end - + def self.create_from_store(record) data = JSON.parse(record.value) data[:name] = record.key new(record.id, data) end - - def self.save_to_store(id = nil, key, data) + + def self.save_to_store(id = nil, key, data) if id record = PluginStoreRow.find_by(id: id, plugin_name: NAMESPACE) return false if !record @@ -192,7 +191,7 @@ class ::CustomWizard::CustomField record.save end end - + def self.destroy(name) if exists?(name) PluginStoreRow.where(plugin_name: NAMESPACE, key: name).destroy_all @@ -202,18 +201,18 @@ class ::CustomWizard::CustomField false end end - + def self.invalidate_cache CustomWizard::Cache.new(LIST_CACHE_KEY).delete Discourse.clear_readonly! Discourse.request_refresh! end - + def self.any? cached_list.length > 0 end - + def self.enabled? any? end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/engine.rb b/lib/custom_wizard/engine.rb index 70e3d18a..12d28a60 100644 --- a/lib/custom_wizard/engine.rb +++ b/lib/custom_wizard/engine.rb @@ -2,9 +2,9 @@ module ::CustomWizard PLUGIN_NAME ||= 'custom_wizard' - + class Engine < ::Rails::Engine engine_name PLUGIN_NAME isolate_namespace CustomWizard end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/field.rb b/lib/custom_wizard/field.rb index f52e2d5a..aa53c8a7 100644 --- a/lib/custom_wizard/field.rb +++ b/lib/custom_wizard/field.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Field def self.types @types ||= { @@ -64,7 +65,7 @@ class CustomWizard::Field @require_assets ||= {} end - def self.register(type, plugin = nil, asset_paths = [], opts={}) + def self.register(type, plugin = nil, asset_paths = [], opts = {}) if type types[type.to_sym] ||= {} types[type.to_sym] = opts[:type_opts] if opts[:type_opts].present? diff --git a/lib/custom_wizard/log.rb b/lib/custom_wizard/log.rb index 7dca2093..fc747440 100644 --- a/lib/custom_wizard/log.rb +++ b/lib/custom_wizard/log.rb @@ -1,18 +1,19 @@ +# frozen_string_literal: true class CustomWizard::Log include ActiveModel::Serialization - + attr_accessor :message, :date - + PAGE_LIMIT = 100 - + def initialize(attrs) @message = attrs['message'] @date = attrs['date'] end - + def self.create(message) log_id = SecureRandom.hex(12) - + PluginStore.set('custom_wizard_log', log_id.to_s, { @@ -21,20 +22,20 @@ class CustomWizard::Log } ) end - + def self.list_query PluginStoreRow.where(" plugin_name = 'custom_wizard_log' AND (value::json->'date') IS NOT NULL ").order("value::json->>'date' DESC") end - + def self.list(page = 0, limit = nil) limit = limit.to_i > 0 ? limit.to_i : PAGE_LIMIT page = page.to_i - + self.list_query.limit(limit) .offset(page * limit) .map { |r| self.new(JSON.parse(r.value)) } end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb index d28daed9..df49c538 100644 --- a/lib/custom_wizard/mapper.rb +++ b/lib/custom_wizard/mapper.rb @@ -1,25 +1,26 @@ +# frozen_string_literal: true class CustomWizard::Mapper attr_accessor :inputs, :data, :user - + USER_FIELDS = [ - 'name', - 'username', - 'email', - 'date_of_birth', - 'title', - 'locale', - 'trust_level', - 'email_level', - 'email_messages_level', + 'name', + 'username', + 'email', + 'date_of_birth', + 'title', + 'locale', + 'trust_level', + 'email_level', + 'email_messages_level', 'email_digests' ] PROFILE_FIELDS = ['location', 'website', 'bio_raw'] - + def self.user_fields USER_FIELDS + PROFILE_FIELDS end - + OPERATORS = { equal: '==', greater: '>', @@ -33,28 +34,28 @@ class CustomWizard::Mapper false: "==" } } - + def initialize(params) @inputs = params[:inputs] || {} @data = params[:data] || {} @user = params[:user] @opts = params[:opts] || {} end - + def perform multiple = @opts[:multiple] perform_result = multiple ? [] : nil - + inputs.each do |input| input_type = input['type'] pairs = input['pairs'] - + if (input_type === 'conditional' && validate_pairs(pairs)) || input_type === 'assignment' output = input['output'] output_type = input['output_type'] - + result = build_result(map_field(output, output_type), input_type) - + if multiple perform_result.push(result) else @@ -62,10 +63,10 @@ class CustomWizard::Mapper break end end - + if input_type === 'validation' result = build_result(validate_pairs(pairs), input_type) - + if multiple perform_result.push(result) else @@ -73,10 +74,10 @@ class CustomWizard::Mapper break end end - + if input_type === 'association' result = build_result(map_pairs(pairs), input_type) - + if multiple perform_result.push(result) else @@ -85,10 +86,10 @@ class CustomWizard::Mapper end end end - + perform_result end - + def build_result(result, type) if @opts[:with_type] { @@ -99,7 +100,7 @@ class CustomWizard::Mapper result end end - + def validate_pairs(pairs) pairs.all? do |pair| connector = pair['connector'] @@ -113,7 +114,7 @@ class CustomWizard::Mapper end end end - + def cast_value(value, key, connector) if connector == 'regex' Regexp.new(value) @@ -127,10 +128,10 @@ class CustomWizard::Mapper end end end - + def validation_result(key, value, operator) result = nil - + if operator.is_a?(Hash) && (operator = operator[value.to_sym]).present? if value == "present" result = key.public_send(operator) @@ -142,21 +143,21 @@ class CustomWizard::Mapper else result = false end - + if operator == '=~' result.nil? ? false : true else result end end - + def map_pairs(pairs) result = [] - + pairs.each do |pair| key = map_field(pair['key'], pair['key_type']) value = map_field(pair['value'], pair['value_type']) - + if key && value result.push( key: key, @@ -164,32 +165,32 @@ class CustomWizard::Mapper ) end end - + result end - + def map_operator(connector) OPERATORS[connector.to_sym] || '==' end - + def map_field(value, type) method = "map_#{type}" - + if self.respond_to?(method) self.send(method, value) else value end end - + def map_text(value) interpolate(value) end - + def map_wizard_field(value) data && !data.key?("submitted_at") && data[value] end - + def map_wizard_action(value) data && !data.key?("submitted_at") && data[value] end @@ -203,7 +204,7 @@ class CustomWizard::Mapper User.find(user.id).send(value) end end - + def map_user_field_options(value) if value.include?(User::USER_FIELD_PREFIX) if field = UserField.find_by(id: value.split('_').last) @@ -211,10 +212,10 @@ class CustomWizard::Mapper end end end - - def interpolate(string, opts={ user: true, wizard: true, value: true }) + + def interpolate(string, opts = { user: true, wizard: true, value: true }) return string if string.blank? - + if opts[:user] string.gsub!(/u\{(.*?)\}/) do |match| result = '' @@ -223,21 +224,21 @@ class CustomWizard::Mapper result end end - + if opts[:wizard] string.gsub!(/w\{(.*?)\}/) do |match| value = recurse(data, [*$1.split('.')]) value.present? ? value : '' end end - + if opts[:value] string.gsub!(/v\{(.*?)\}/) do |match| attrs = $1.split(':') key = attrs.first format = attrs.last if attrs.length > 1 result = '' - + if key == 'time' time_format = format.present? ? format : "%B %-d, %Y" result = Time.now.strftime(time_format) @@ -246,10 +247,10 @@ class CustomWizard::Mapper result end end - + string end - + def recurse(data, keys) return nil if data.nil? k = keys.shift diff --git a/lib/custom_wizard/realtime_validation.rb b/lib/custom_wizard/realtime_validation.rb index 69341ebf..6f65efaa 100644 --- a/lib/custom_wizard/realtime_validation.rb +++ b/lib/custom_wizard/realtime_validation.rb @@ -2,7 +2,7 @@ class CustomWizard::RealtimeValidation cattr_accessor :types - + @@types ||= { similar_topics: { types: [:text], diff --git a/lib/custom_wizard/realtime_validations/result.rb b/lib/custom_wizard/realtime_validations/result.rb index 988bea73..413248b7 100644 --- a/lib/custom_wizard/realtime_validations/result.rb +++ b/lib/custom_wizard/realtime_validations/result.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::RealtimeValidation::Result attr_accessor :type, :items, @@ -8,4 +9,4 @@ class CustomWizard::RealtimeValidation::Result @items = [] @serializer_opts = {} end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/realtime_validations/similar_topics.rb b/lib/custom_wizard/realtime_validations/similar_topics.rb index 3323a2ee..2c99cf43 100644 --- a/lib/custom_wizard/realtime_validations/similar_topics.rb +++ b/lib/custom_wizard/realtime_validations/similar_topics.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true class CustomWizard::RealtimeValidation::SimilarTopics attr_accessor :user - + def initialize(user) @user = user end - + class SimilarTopic def initialize(topic) @topic = topic @@ -16,7 +17,7 @@ class CustomWizard::RealtimeValidation::SimilarTopics Search::GroupedSearchResults.blurb_for(cooked: @topic.try(:blurb)) end end - + def perform(params) title = params[:title] raw = params[:raw] @@ -25,7 +26,7 @@ class CustomWizard::RealtimeValidation::SimilarTopics time_unit = params[:time_unit] result = CustomWizard::RealtimeValidation::Result.new(:similar_topic) - + if title.length < SiteSetting.min_title_similar_length || !Topic.count_exceeds_minimum? return result end @@ -38,10 +39,10 @@ class CustomWizard::RealtimeValidation::SimilarTopics end topics.map! { |t| SimilarTopic.new(t) } - + result.items = topics result.serializer_opts = { root: :similar_topics } - + result end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/step_updater.rb b/lib/custom_wizard/step_updater.rb index 26513a9a..3a9d65f1 100644 --- a/lib/custom_wizard/step_updater.rb +++ b/lib/custom_wizard/step_updater.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::StepUpdater include ActiveModel::Model @@ -17,9 +18,9 @@ class CustomWizard::StepUpdater @step.present? && @step.updater.present? && success? - + @step.updater.call(self) - + UserHistory.create( action: UserHistory.actions[:custom_wizard_step], acting_user_id: @current_user.id, @@ -38,7 +39,7 @@ class CustomWizard::StepUpdater def refresh_required? @refresh_required end - + def validate CustomWizard::UpdateValidator.new(self).perform end diff --git a/lib/custom_wizard/template.rb b/lib/custom_wizard/template.rb index 8329ea61..91b97f73 100644 --- a/lib/custom_wizard/template.rb +++ b/lib/custom_wizard/template.rb @@ -2,87 +2,87 @@ class CustomWizard::Template include HasErrors - + attr_reader :data, :opts - + def initialize(data) @data = data end - - def save(opts={}) + + def save(opts = {}) @opts = opts - + normalize_data validate_data prepare_data - + return false if errors.any? - + ActiveRecord::Base.transaction do schedule_save_jobs unless opts[:skip_jobs] PluginStore.set(CustomWizard::PLUGIN_NAME, @data[:id], @data) end - + @data[:id] end - - def self.save(data, opts={}) + + def self.save(data, opts = {}) new(data).save(opts) end - + def self.find(wizard_id) PluginStore.get(CustomWizard::PLUGIN_NAME, wizard_id) end - + def self.remove(wizard_id) wizard = CustomWizard::Wizard.create(wizard_id) - + return false if !wizard - - ActiveRecord::Base.transaction do + + ActiveRecord::Base.transaction do PluginStore.remove(CustomWizard::PLUGIN_NAME, wizard.id) - + if wizard.after_time Jobs.cancel_scheduled_job(:set_after_time_wizard) Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard_id) end end - + true end - + def self.exists?(wizard_id) PluginStoreRow.exists?(plugin_name: 'custom_wizard', key: wizard_id) end - + def self.list(setting: nil, order: :id) query = "plugin_name = 'custom_wizard'" query += "AND (value::json ->> '#{setting}')::boolean IS TRUE" if setting - + PluginStoreRow.where(query).order(order) .reduce([]) do |result, record| attrs = JSON.parse(record.value) - + if attrs.present? && attrs.is_a?(Hash) && attrs['id'].present? && attrs['name'].present? - + result.push(attrs) end - + result end end - + private - + def normalize_data @data = ::JSON.parse(@data) if @data.is_a?(String) @data = @data.with_indifferent_access end - + def prepare_data @data[:steps].each do |step| if step[:raw_description] @@ -90,25 +90,25 @@ class CustomWizard::Template end end end - + def validate_data validator = CustomWizard::TemplateValidator.new(@data, @opts) validator.perform add_errors_from(validator) end - + def schedule_save_jobs if @data[:after_time] && @data[:after_time_scheduled] wizard_id = @data[:id] old_data = CustomWizard::Template.find(data[:id]) - + begin enqueue_wizard_at = Time.parse(@data[:after_time_scheduled]).utc rescue ArgumentError errors.add :validation, I18n.t("wizard.validation.after_time") raise ActiveRecord::Rollback.new end - + if enqueue_wizard_at Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id) Jobs.enqueue_at(enqueue_wizard_at, :set_after_time_wizard, wizard_id: wizard_id) @@ -118,4 +118,4 @@ class CustomWizard::Template end end end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/validators/template.rb b/lib/custom_wizard/validators/template.rb index 2ed67deb..c90944e9 100644 --- a/lib/custom_wizard/validators/template.rb +++ b/lib/custom_wizard/validators/template.rb @@ -1,42 +1,43 @@ +# frozen_string_literal: true class CustomWizard::TemplateValidator include HasErrors include ActiveModel::Model - - def initialize(data, opts={}) + + def initialize(data, opts = {}) @data = data @opts = opts end - + def perform data = @data - + check_id(data, :wizard) check_required(data, :wizard) validate_after_time - + data[:steps].each do |step| check_required(step, :step) - + if data[:fields].present? data[:fields].each do |field| check_required(field, :field) end end end - + if data[:actions].present? data[:actions].each do |action| check_required(action, :action) end end - - if errors.any? + + if errors.any? false else true end end - + def self.required { wizard: ['id', 'name', 'steps'], @@ -45,13 +46,13 @@ class CustomWizard::TemplateValidator action: ['id', 'type'] } end - + private - + def check_required(object, type) - CustomWizard::TemplateValidator.required[type].each do |property| + CustomWizard::TemplateValidator.required[type].each do |property| if object[property].blank? - errors.add :base, I18n.t("wizard.validation.required", property: property) + errors.add :base, I18n.t("wizard.validation.required", property: property) end end end @@ -61,14 +62,14 @@ class CustomWizard::TemplateValidator errors.add :base, I18n.t("wizard.validation.conflict", wizard_id: object[:id]) end end - + def validate_after_time return unless @data[:after_time] - + wizard = CustomWizard::Wizard.create(@data[:id]) if !@opts[:create] current_time = wizard.present? ? wizard.after_time_scheduled : nil new_time = @data[:after_time_scheduled] - + begin active_time = Time.parse(new_time.present? ? new_time : current_time).utc rescue ArgumentError @@ -79,4 +80,4 @@ class CustomWizard::TemplateValidator errors.add :base, I18n.t("wizard.validation.after_time") end end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/validators/update.rb b/lib/custom_wizard/validators/update.rb index 9a586359..d84b448a 100644 --- a/lib/custom_wizard/validators/update.rb +++ b/lib/custom_wizard/validators/update.rb @@ -1,21 +1,22 @@ +# frozen_string_literal: true require 'addressable/uri' class ::CustomWizard::UpdateValidator attr_reader :updater - + def initialize(updater) @updater = updater end - + def perform updater.step.fields.each do |field| validate_field(field) end end - + def validate_field(field) return if field.type == 'text_only' - + field_id = field.id.to_s value = @updater.submission[field_id] min_length = false @@ -26,7 +27,7 @@ class ::CustomWizard::UpdateValidator max_length = field.max_length if is_text_type(field) file_types = field.file_types format = field.format - + if required && !value @updater.errors.add(field_id, I18n.t('wizard.field.required', label: label)) end @@ -46,26 +47,26 @@ class ::CustomWizard::UpdateValidator if type === 'checkbox' @updater.submission[field_id] = standardise_boolean(value) end - + if type === 'upload' && value.present? && !validate_file_type(value, file_types) @updater.errors.add(field_id, I18n.t('wizard.field.invalid_file', label: label, types: file_types)) end - + if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value) @updater.errors.add(field_id, I18n.t('wizard.field.invalid_date')) end - + if type === 'time' && value.present? && !validate_time(value) @updater.errors.add(field_id, I18n.t('wizard.field.invalid_time')) - end - + end + self.class.field_validators.each do |validator| if type === validator[:type] validator[:block].call(field, value, @updater) end end end - + def self.sorted_field_validators @sorted_field_validators ||= [] end @@ -78,15 +79,15 @@ class ::CustomWizard::UpdateValidator sorted_field_validators << { priority: priority, type: type, block: block } @sorted_field_validators.sort_by! { |h| -h[:priority] } end - + private - + def validate_file_type(value, file_types) file_types.split(',') .map { |t| t.gsub('.', '') } .include?(File.extname(value['original_filename'])[1..-1]) end - + def validate_date(value) begin Date.parse(value) @@ -95,7 +96,7 @@ class ::CustomWizard::UpdateValidator false end end - + def validate_time(value) begin Time.parse(value) @@ -112,17 +113,17 @@ class ::CustomWizard::UpdateValidator def is_url_type(field) ['url'].include? field.type end - + SCHEMES ||= %w(http https) - + def check_if_url(url) parsed = Addressable::URI.parse(url) or return false SCHEMES.include?(parsed.scheme) rescue Addressable::URI::InvalidURIError false end - + def standardise_boolean(value) ActiveRecord::Type::Boolean.new.cast(value) end -end \ No newline at end of file +end diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb index 4033d4a1..bf3478ca 100644 --- a/lib/custom_wizard/wizard.rb +++ b/lib/custom_wizard/wizard.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_dependency 'wizard/step' require_dependency 'wizard/field' require_dependency 'wizard/step_updater' @@ -29,10 +30,10 @@ class CustomWizard::Wizard :user, :first_step - def initialize(attrs = {}, user=nil) + def initialize(attrs = {}, user = nil) @user = user attrs = attrs.with_indifferent_access - + @id = attrs['id'] @name = attrs['name'] @background = attrs['background'] @@ -48,21 +49,21 @@ class CustomWizard::Wizard @needs_categories = false @needs_groups = false @theme_id = attrs['theme_id'] - + if attrs['theme'].present? theme = ::Theme.find_by(name: attrs['theme']) @theme_id = theme.id if theme end - + @first_step = nil @steps = [] if attrs['steps'].present? @step_ids = attrs['steps'].map { |s| s['id'] } end - + @actions = [] end - + def cast_bool(val) val.nil? ? false : ActiveRecord::Type::Boolean.new.cast(val) end @@ -73,12 +74,12 @@ class CustomWizard::Wizard def append_step(step) step = create_step(step) if step.is_a?(String) - + yield step if block_given? last_step = steps.last steps << step - + if steps.size == 1 @first_step = step step.index = 0 @@ -133,7 +134,7 @@ class CustomWizard::Wizard def completed? return nil if !user - + history = ::UserHistory.where( acting_user_id: user.id, action: ::UserHistory.actions[:custom_wizard_step], @@ -143,7 +144,7 @@ class CustomWizard::Wizard if after_time history = history.where("updated_at > ?", after_time_scheduled) end - + completed = history.distinct.order(:subject).pluck(:subject) (step_ids - completed).empty? end @@ -151,7 +152,7 @@ class CustomWizard::Wizard def permitted? return false unless user return true if user.admin? || permitted.blank? - + mapper = CustomWizard::Mapper.new( inputs: permitted, user: user, @@ -160,9 +161,9 @@ class CustomWizard::Wizard multiple: true } ).perform - + return true if mapper.blank? - + mapper.all? do |m| if m[:type] === 'assignment' GroupUser.exists?(group_id: m[:result], user_id: user.id) @@ -173,11 +174,11 @@ class CustomWizard::Wizard end end end - + def can_access? return false unless user return true if user.admin - return permitted? && (multiple_submissions || !completed?) + permitted? && (multiple_submissions || !completed?) end def reset @@ -188,19 +189,19 @@ class CustomWizard::Wizard subject: "reset" ) end - + def categories @categories ||= ::Site.new(Guardian.new(user)).categories end - + def groups @groups ||= ::Site.new(Guardian.new(user)).groups end - + def submissions Array.wrap(PluginStore.get("#{id}_submissions", user.id)) end - + def current_submission if submissions.present? && !submissions.last.key?("submitted_at") submissions.last @@ -208,19 +209,19 @@ class CustomWizard::Wizard nil end end - + def set_submissions(submissions) PluginStore.set("#{id}_submissions", user.id, Array.wrap(submissions)) 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) @@ -228,10 +229,10 @@ class CustomWizard::Wizard false end end - + def self.list(user, template_opts: {}, not_completed: false) return [] unless user - + CustomWizard::Template.list(template_opts).reduce([]) do |result, template| wizard = new(template, user) result.push(wizard) if wizard.can_access? && ( @@ -279,7 +280,7 @@ class CustomWizard::Wizard def self.set_wizard_redirect(wizard_id, user) wizard = self.create(wizard_id, user) - + if wizard.permitted? user.custom_fields['redirect_to_wizard'] = wizard_id user.save_custom_fields(true) diff --git a/plugin.rb b/plugin.rb index 19402116..91970d15 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # name: discourse-custom-wizard # about: Create custom wizards # version: 0.7.0 @@ -95,7 +96,7 @@ after_initialize do ].each do |path| load File.expand_path(path, __FILE__) end - + add_class_method(:wizard, :user_requires_completion?) do |user| wizard_result = self.new(user).requires_completion? return wizard_result if wizard_result @@ -114,7 +115,7 @@ after_initialize do !!custom_redirect end - + add_to_class(:users_controller, :wizard_path) do if custom_wizard_redirect = current_user.custom_fields['redirect_to_wizard'] "#{Discourse.base_url}/w/#{custom_wizard_redirect.dasherize}" @@ -132,13 +133,13 @@ after_initialize do CustomWizard::Wizard.set_wizard_redirect(wizard.id, user) end end - + add_to_class(:application_controller, :redirect_to_wizard_if_required) do wizard_id = current_user.custom_fields['redirect_to_wizard'] @excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split('|') + ['/w/'] url = request.referer || request.original_url - if request.format === 'text/html' && !@excluded_routes.any? {|str| /#{str}/ =~ url} && wizard_id + 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) end @@ -147,37 +148,37 @@ after_initialize do end end end - + add_to_serializer(:site, :include_wizard_required?) do scope.is_admin? && Wizard.new(scope.user).requires_completion? end - + add_to_serializer(:site, :complete_custom_wizard) do if scope.user && requires_completion = CustomWizard::Wizard.prompt_completion(scope.user) - requires_completion.map {|w| { name: w[:name], url: "/w/#{w[:id]}"} } + requires_completion.map { |w| { name: w[:name], url: "/w/#{w[:id]}" } } end end add_to_serializer(:site, :include_complete_custom_wizard?) do complete_custom_wizard.present? end - + add_model_callback(:application_controller, :before_action) do redirect_to_wizard_if_required if current_user end - + ::ExtraLocalesController.prepend ExtraLocalesControllerCustomWizard ::InvitesController.prepend InvitesControllerCustomWizard ::UsersController.prepend CustomWizardUsersController ::Wizard::Field.prepend CustomWizardFieldExtension ::Wizard::Step.prepend CustomWizardStepExtension - + full_path = "#{Rails.root}/plugins/discourse-custom-wizard/assets/stylesheets/wizard/wizard_custom.scss" DiscoursePluginRegistry.register_asset(full_path, {}, "wizard_custom") Stylesheet::Importer.register_import("wizard_custom") do import_files(DiscoursePluginRegistry.stylesheets["wizard_custom"]) end - + CustomWizard::CustomField::CLASSES.keys.each do |klass| add_model_callback(klass, :after_initialize) do if CustomWizard::CustomField.enabled? @@ -189,10 +190,10 @@ after_initialize do end end end - + klass.to_s.classify.constantize.singleton_class.prepend CustomWizardCustomFieldPreloader end - + CustomWizard::CustomField.serializers.each do |serializer_klass| "#{serializer_klass}_serializer".classify.constantize.prepend CustomWizardCustomFieldSerializer end diff --git a/serializers/custom_wizard/api/authorization_serializer.rb b/serializers/custom_wizard/api/authorization_serializer.rb index fe6e7444..f1912eea 100644 --- a/serializers/custom_wizard/api/authorization_serializer.rb +++ b/serializers/custom_wizard/api/authorization_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Api::AuthorizationSerializer < ::ApplicationSerializer attributes :auth_type, :auth_url, diff --git a/serializers/custom_wizard/api/basic_endpoint_serializer.rb b/serializers/custom_wizard/api/basic_endpoint_serializer.rb index 63758c48..2c81f9e8 100644 --- a/serializers/custom_wizard/api/basic_endpoint_serializer.rb +++ b/serializers/custom_wizard/api/basic_endpoint_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Api::BasicEndpointSerializer < ::ApplicationSerializer attributes :id, :name diff --git a/serializers/custom_wizard/api/endpoint_serializer.rb b/serializers/custom_wizard/api/endpoint_serializer.rb index 0430bea3..99af63c3 100644 --- a/serializers/custom_wizard/api/endpoint_serializer.rb +++ b/serializers/custom_wizard/api/endpoint_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::Api::EndpointSerializer < ::ApplicationSerializer attributes :id, :name, diff --git a/serializers/custom_wizard/api/log_serializer.rb b/serializers/custom_wizard/api/log_serializer.rb index 819185b5..156f8c62 100644 --- a/serializers/custom_wizard/api/log_serializer.rb +++ b/serializers/custom_wizard/api/log_serializer.rb @@ -1,12 +1,13 @@ -class CustomWizard::Api::LogSerializer < ::ApplicationSerializer - attributes :log_id, - :time, - :status, - :url, - :error, - :user_id, - :username, - :userpath, - :name, - :avatar_template -end +# frozen_string_literal: true +class CustomWizard::Api::LogSerializer < ::ApplicationSerializer + attributes :log_id, + :time, + :status, + :url, + :error, + :user_id, + :username, + :userpath, + :name, + :avatar_template +end diff --git a/serializers/custom_wizard/api_serializer.rb b/serializers/custom_wizard/api_serializer.rb index 1fa601a3..0bf5707d 100644 --- a/serializers/custom_wizard/api_serializer.rb +++ b/serializers/custom_wizard/api_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::ApiSerializer < ::ApplicationSerializer attributes :name, :title, diff --git a/serializers/custom_wizard/basic_api_serializer.rb b/serializers/custom_wizard/basic_api_serializer.rb index 5b037650..56094b49 100644 --- a/serializers/custom_wizard/basic_api_serializer.rb +++ b/serializers/custom_wizard/basic_api_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::BasicApiSerializer < ::ApplicationSerializer attributes :name, :title, diff --git a/serializers/custom_wizard/basic_wizard_serializer.rb b/serializers/custom_wizard/basic_wizard_serializer.rb index 76c94614..06b5781d 100644 --- a/serializers/custom_wizard/basic_wizard_serializer.rb +++ b/serializers/custom_wizard/basic_wizard_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::BasicWizardSerializer < ::ApplicationSerializer attributes :id, :name -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/custom_field_serializer.rb b/serializers/custom_wizard/custom_field_serializer.rb index 9d684be3..8f0c3fd8 100644 --- a/serializers/custom_wizard/custom_field_serializer.rb +++ b/serializers/custom_wizard/custom_field_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::CustomFieldSerializer < ApplicationSerializer attributes :id, :klass, :name, :type, :serializers -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/log_serializer.rb b/serializers/custom_wizard/log_serializer.rb index 5b88d3f0..e521c573 100644 --- a/serializers/custom_wizard/log_serializer.rb +++ b/serializers/custom_wizard/log_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CustomWizard::LogSerializer < ApplicationSerializer attributes :message, :date -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb b/serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb index 976eef1b..17f9e255 100644 --- a/serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb +++ b/serializers/custom_wizard/realtime_validation/similar_topics_serializer.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class ::CustomWizard::RealtimeValidation::SimilarTopicsSerializer < ::SimilarTopicSerializer -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/wizard_field_serializer.rb b/serializers/custom_wizard/wizard_field_serializer.rb index e89d5f0c..f9c42e6c 100644 --- a/serializers/custom_wizard/wizard_field_serializer.rb +++ b/serializers/custom_wizard/wizard_field_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class CustomWizard::FieldSerializer < ::WizardFieldSerializer - + attributes :image, :file_types, :format, @@ -38,23 +38,23 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer def file_types object.file_types end - + def format object.format end - + def limit object.limit end - + def property object.property end - + def content object.content end - + def include_choices? object.choices.present? end @@ -81,4 +81,4 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer def number object.number end -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/wizard_serializer.rb b/serializers/custom_wizard/wizard_serializer.rb index 93596e24..5f929ea0 100644 --- a/serializers/custom_wizard/wizard_serializer.rb +++ b/serializers/custom_wizard/wizard_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer - + attributes :start, :background, :theme_id, @@ -9,7 +9,7 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer :required, :permitted, :uncategorized_category_id - + has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects has_one :user, serializer: ::BasicUserSerializer, embed: :objects has_many :categories, serializer: ::BasicCategorySerializer, embed: :objects @@ -28,7 +28,7 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer def permitted object.permitted? end - + def start object.start.id end @@ -40,20 +40,20 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer def include_steps? !include_completed? end - + def include_categories? object.needs_categories end - + def include_groups? object.needs_groups end - + def uncategorized_category_id SiteSetting.uncategorized_category_id end - + def include_uncategorized_category_id? object.needs_categories end -end \ No newline at end of file +end diff --git a/serializers/custom_wizard/wizard_step_serializer.rb b/serializers/custom_wizard/wizard_step_serializer.rb index 2cd74393..b5648e46 100644 --- a/serializers/custom_wizard/wizard_step_serializer.rb +++ b/serializers/custom_wizard/wizard_step_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class CustomWizard::StepSerializer < ::WizardStepSerializer - + attributes :permitted, :permitted_message has_many :fields, serializer: ::CustomWizard::FieldSerializer, embed: :objects @@ -18,8 +18,8 @@ class CustomWizard::StepSerializer < ::WizardStepSerializer def permitted object.permitted end - + def permitted_message object.permitted_message end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/action_spec.rb b/spec/components/custom_wizard/action_spec.rb index 751f592f..9ccb51bf 100644 --- a/spec/components/custom_wizard/action_spec.rb +++ b/spec/components/custom_wizard/action_spec.rb @@ -4,13 +4,13 @@ describe CustomWizard::Action do fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) } fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') } fab!(:group) { Fabricate(:group) } - + let(:open_composer) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/actions/open_composer.json" ).read) } - + before do Group.refresh_automatic_group!(:trust_level_2) CustomWizard::Template.save( @@ -20,7 +20,7 @@ describe CustomWizard::Action do skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - + context 'creating a topic' do it "works" do wizard = CustomWizard::Builder.new(@template[:id], user).build @@ -33,7 +33,7 @@ describe CustomWizard::Action do wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id ).update - + topic = Topic.where( title: "Topic Title", category_id: category.id @@ -44,7 +44,7 @@ describe CustomWizard::Action do raw: "topic body" ).exists?).to eq(true) end - + it "fails silently without basic topic inputs" do wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater( @@ -54,7 +54,7 @@ describe CustomWizard::Action do wizard.create_updater(wizard.steps.second.id, {}).update updater = wizard.create_updater(wizard.steps.last.id, {}) updater.update - + expect(updater.success?).to eq(true) expect(UserHistory.where( acting_user_id: user.id, @@ -66,29 +66,29 @@ describe CustomWizard::Action do ).exists?).to eq(false) end end - + it 'sends a message' do User.create(username: 'angus1', email: "angus1@email.com") - + wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater(wizard.steps[0].id, {}).update wizard.create_updater(wizard.steps[1].id, {}).update - + topic = Topic.where( archetype: Archetype.private_message, title: "Message title" ) - + post = Post.where( topic_id: topic.pluck(:id), raw: "I will interpolate some wizard fields" ) - + expect(topic.exists?).to eq(true) expect(topic.first.topic_allowed_users.first.user.username).to eq('angus1') expect(post.exists?).to eq(true) end - + it 'updates a profile' do wizard = CustomWizard::Builder.new(@template[:id], user).build upload = Upload.create!( @@ -104,28 +104,28 @@ describe CustomWizard::Action do ).update expect(user.profile_background_upload.id).to eq(upload.id) end - + context "open composer" do it 'works' do wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update - + updater = wizard.create_updater(wizard.steps[1].id, {}) updater.update - + category = Category.find_by(id: wizard.current_submission['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" ) end - + it 'encodes special characters in the title and body' do open_composer['title'][0]['output'] = "Title that's special $" open_composer['post_template'] = "Body & more body & more body" - + wizard = CustomWizard::Wizard.new(@template, user) - + action = CustomWizard::Action.new( wizard: wizard, action: open_composer, @@ -133,30 +133,30 @@ describe CustomWizard::Action do data: {} ) action.perform - + expect(action.result.success?).to eq(true) - + decoded_output = CGI.parse(URI.parse(action.result.output).query) - + expect(decoded_output['title'][0]).to eq("Title that's special $") expect(decoded_output['body'][0]).to eq("Body & more body & more body") end end - + it 'creates a category' 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) end - + it 'creates 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 expect(Group.where(name: wizard.current_submission['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 @@ -164,7 +164,7 @@ describe CustomWizard::Action do group = Group.find_by(name: wizard.current_submission['action_9']) expect(group.users.first.username).to eq('angus') end - + it 'watches categories' do wizard = CustomWizard::Builder.new(@template[:id], user).build wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update @@ -178,7 +178,7 @@ describe CustomWizard::Action do user_id: user.id ).first.notification_level).to eq(0) end - + it 're-routes a user' do wizard = CustomWizard::Builder.new(@template[:id], user).build updater = wizard.create_updater(wizard.steps.last.id, {}) diff --git a/spec/components/custom_wizard/builder_spec.rb b/spec/components/custom_wizard/builder_spec.rb index e5a51905..9ad4348e 100644 --- a/spec/components/custom_wizard/builder_spec.rb +++ b/spec/components/custom_wizard/builder_spec.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require_relative '../../plugin_helper' describe CustomWizard::Builder do @@ -9,31 +7,31 @@ describe CustomWizard::Builder do username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3] - ) + ) } fab!(:user) { Fabricate(:user) } fab!(:category1) { Fabricate(:category, name: 'cat1') } fab!(:category2) { Fabricate(:category, name: 'cat2') } fab!(:group) { Fabricate(:group) } - + let(:required_data_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/step/required_data.json" ).read) } - + let(:permitted_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard/permitted.json" ).read) } - + let(:permitted_param_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/step/permitted_params.json" ).read) } - + before do Group.refresh_automatic_group!(:trust_level_3) CustomWizard::Template.save( @@ -43,51 +41,51 @@ describe CustomWizard::Builder do skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - + context 'disabled' do before do SiteSetting.custom_wizard_enabled = false end - + it "returns nil" do expect( CustomWizard::Builder.new(@template[:id], user).build ).to eq(nil) end end - + context 'enabled' do before do SiteSetting.custom_wizard_enabled = true end - + it "returns wizard metadata" do wizard = CustomWizard::Builder.new(@template[:id], user).build expect(wizard.id).to eq("super_mega_fun_wizard") expect(wizard.name).to eq("Super Mega Fun Wizard") expect(wizard.background).to eq("#333333") end - + it "returns steps" do expect( CustomWizard::Builder.new(@template[:id], user).build .steps.length ).to eq(3) end - + context "with multiple submissions disabled" do before do @template[:multiple_submissions] = false CustomWizard::Template.save(@template.as_json) end - + it 'returns steps if user has not completed it' do expect( CustomWizard::Builder.new(@template[:id], user).build .steps.length ).to eq(3) end - + it 'returns no steps if user has completed it' do @template[:steps].each do |step| UserHistory.create!( @@ -100,62 +98,62 @@ describe CustomWizard::Builder do ) ) end - + expect( CustomWizard::Builder.new(@template[:id], user).build .steps.length ).to eq(0) end end - + context "with restricted permissions" do before do @template[:permitted] = permitted_json["permitted"] CustomWizard::Template.save(@template.as_json) end - + it 'is not permitted if user is not in permitted group' do expect( CustomWizard::Builder.new(@template[:id], user).build .permitted? ).to eq(false) end - + it 'user cannot access if not permitted' do expect( CustomWizard::Builder.new(@template[:id], user).build .can_access? ).to eq(false) end - + it 'returns wizard metadata if user is not permitted' do expect( CustomWizard::Builder.new(@template[:id], user).build .name ).to eq("Super Mega Fun Wizard") end - + it 'returns no steps if user is not permitted' do expect( CustomWizard::Builder.new(@template[:id], user).build .steps.length ).to eq(0) end - + it 'is permitted if user is in permitted group' do expect( CustomWizard::Builder.new(@template[:id], trusted_user).build .permitted? ).to eq(true) end - + it 'user can access if permitted' do expect( CustomWizard::Builder.new(@template[:id], trusted_user).build .can_access? ).to eq(true) end - + it 'returns steps if user is permitted' do expect( CustomWizard::Builder.new(@template[:id], trusted_user).build @@ -163,7 +161,7 @@ describe CustomWizard::Builder do ).to eq(3) end end - + it 'returns prefilled data' do expect( CustomWizard::Builder.new(@template[:id], user).build @@ -172,13 +170,13 @@ describe CustomWizard::Builder do .value ).to eq('I am prefilled') end - + 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') end - + it 'returns saved submissions' do expect( CustomWizard::Builder.new(@template[:id], user).build @@ -187,13 +185,13 @@ describe CustomWizard::Builder do .value ).to eq('I am a user submission') end - + context "restart is enabled" do before do @template[:restart_on_revisit] = true CustomWizard::Template.save(@template.as_json) end - + it 'does not return saved submissions' do expect( CustomWizard::Builder.new(@template[:id], user).build @@ -210,19 +208,19 @@ describe CustomWizard::Builder do first_step = CustomWizard::Builder.new(@template[:id], user) .build(reset: true) .steps.first - + expect(first_step.id).to eq("step_1") expect(first_step.title).to eq("Text") expect(first_step.description).to eq("

Text inputs!

") end - + context 'with required data' do before do @template[:steps][0][:required_data] = required_data_json['required_data'] @template[:steps][0][:required_data_message] = required_data_json['required_data_message'] CustomWizard::Template.save(@template.as_json) end - + it 'is not permitted if required data is not present' do expect( CustomWizard::Builder.new(@template[:id], user).build @@ -230,7 +228,7 @@ describe CustomWizard::Builder do .permitted ).to eq(false) end - + it 'it shows required data message' do expect( CustomWizard::Builder.new(@template[:id], user).build @@ -238,7 +236,7 @@ describe CustomWizard::Builder do .permitted_message ).to eq("Missing required data") end - + it 'is permitted if required data is present' do CustomWizard::Wizard.set_submissions('super_mega_fun_wizard', user, required_data: "required_value" @@ -250,33 +248,33 @@ describe CustomWizard::Builder do ).to eq(true) end end - + context "with permitted params" do before do @template[:steps][0][:permitted_params] = permitted_param_json['permitted_params'] CustomWizard::Template.save(@template.as_json) end - + it 'saves permitted params' do wizard = CustomWizard::Builder.new(@template[:id], user).build({}, param: 'param_value' - ) + ) expect(wizard.current_submission['saved_param']).to eq('param_value') end end end - + context 'building field' do it 'returns field metadata' do wizard = CustomWizard::Builder.new(@template[:id], user).build field = wizard.steps.first.fields.first - + expect(field.label).to eq("

Text

") expect(field.type).to eq("text") expect(field.id).to eq("step_1_field_1") expect(field.min_length).to eq("3") end - + it 'returns all step fields' do expect( CustomWizard::Builder.new(@template[:id], user) @@ -286,7 +284,7 @@ describe CustomWizard::Builder do ).to eq(4) end end - + context 'on update' do def perform_update(step_id, submission) wizard = CustomWizard::Builder.new(@template[:id], user).build @@ -294,7 +292,7 @@ describe CustomWizard::Builder do updater.update updater end - + it 'saves submissions' do perform_update('step_1', step_1_field_1: 'Text input') expect( @@ -302,13 +300,13 @@ describe CustomWizard::Builder do .first['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) end - + it "does not save submissions" do perform_update('step_1', step_1_field_1: 'Text input') expect( @@ -318,4 +316,4 @@ describe CustomWizard::Builder do end end end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/cache_spec.rb b/spec/components/custom_wizard/cache_spec.rb index 13f6a782..2cc3b81a 100644 --- a/spec/components/custom_wizard/cache_spec.rb +++ b/spec/components/custom_wizard/cache_spec.rb @@ -4,31 +4,31 @@ require_relative '../../plugin_helper.rb' describe CustomWizard::Cache do it "writes and reads values to the cache" do - CustomWizard::Cache.new('list').write([1,2,3]) - expect(CustomWizard::Cache.new('list').read).to eq([1,2,3]) + CustomWizard::Cache.new('list').write([1, 2, 3]) + expect(CustomWizard::Cache.new('list').read).to eq([1, 2, 3]) end - + it "deletes values from the cache" do CustomWizard::Cache.new('list').delete expect(CustomWizard::Cache.new('list').read).to eq(nil) end - + describe "#wrap" do before do - @raw = [1,2,3] + @raw = [1, 2, 3] end - + def list CustomWizard::Cache.wrap('list') { @raw } end - + it "returns value from passed block" do - expect(list).to eq([1,2,3]) + expect(list).to eq([1, 2, 3]) end - + it "returns cached value" do cached = list - @raw = [3,2,1] + @raw = [3, 2, 1] expect(list).to eq(cached) end end diff --git a/spec/components/custom_wizard/custom_field_spec.rb b/spec/components/custom_wizard/custom_field_spec.rb index bbedb514..3c9f1706 100644 --- a/spec/components/custom_wizard/custom_field_spec.rb +++ b/spec/components/custom_wizard/custom_field_spec.rb @@ -3,17 +3,17 @@ require_relative '../../plugin_helper' describe CustomWizard::CustomField do - + let(:custom_field_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json" ).read) } - + before do CustomWizard::CustomField.invalidate_cache end - + it "saves custom field records" do custom_field_json['custom_fields'].each do |field_json| custom_field = CustomWizard::CustomField.new(nil, field_json) @@ -23,38 +23,38 @@ describe CustomWizard::CustomField do plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND key = '#{custom_field.name}' AND value::jsonb = '#{field_json.except('name').to_json}'::jsonb - ", ).exists? + ",).exists? ).to eq(true) end end - + it "updates existing custom field records" do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save end - + updated_field_json = custom_field_json['custom_fields'][0] updated_field_json['serializers'] = ["topic_view"] existing_field = CustomWizard::CustomField.find_by_name(updated_field_json["name"]) updated_field = CustomWizard::CustomField.new(existing_field.id, updated_field_json) - + expect(updated_field.save).to eq(true) expect( PluginStoreRow.where(" plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND key = '#{updated_field.name}' AND value::jsonb = '#{updated_field_json.except('name').to_json}'::jsonb - ", ).exists? + ",).exists? ).to eq(true) end - + context "validation" do it "does not save with an unsupported class" do invalid_field_json = custom_field_json['custom_fields'].first invalid_field_json['klass'] = 'user' - + custom_field = CustomWizard::CustomField.new(nil, invalid_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( @@ -67,14 +67,14 @@ describe CustomWizard::CustomField do ).exists? ).to eq(false) end - + it "does not save with an unsupported serializer" do invalid_field_json = custom_field_json['custom_fields'].first invalid_field_json['klass'] = 'category' invalid_field_json['serializers'] = ['category', 'site_category'] - + custom_field = CustomWizard::CustomField.new(nil, invalid_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( @@ -90,13 +90,13 @@ describe CustomWizard::CustomField do ).exists? ).to eq(false) end - + it "does not save with an unsupported type" do invalid_field_json = custom_field_json['custom_fields'].first invalid_field_json['type'] = 'bigint' - + custom_field = CustomWizard::CustomField.new(nil, invalid_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( @@ -109,13 +109,13 @@ describe CustomWizard::CustomField do ).exists? ).to eq(false) end - + it "does not save with a short field name" do invalid_field_json = custom_field_json['custom_fields'].first invalid_field_json['name'] = 'cf' - + custom_field = CustomWizard::CustomField.new(nil, invalid_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( @@ -128,28 +128,28 @@ describe CustomWizard::CustomField do ).exists? ).to eq(false) end - + it "does not save with an existing name if new" do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save end - + first_field_json = custom_field_json['custom_fields'][0] custom_field = CustomWizard::CustomField.new(nil, first_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( I18n.t("wizard.custom_field.error.name_already_taken", name: "topic_field_1") ) end - + it "does not save with an invalid name" do invalid_field_json = custom_field_json['custom_fields'].first invalid_field_json['name'] = ["invalid_name"] - + custom_field = CustomWizard::CustomField.new(nil, invalid_field_json) - + expect(custom_field.save).to eq(false) expect(custom_field.valid?).to eq(false) expect(custom_field.errors.full_messages.first).to eq( @@ -163,31 +163,31 @@ describe CustomWizard::CustomField do ).to eq(false) end end - + context "lists" do before do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save end end - + it "lists saved custom field records" do expect(CustomWizard::CustomField.list.length).to eq(4) end - + it "lists saved custom field records by attribute value" do expect(CustomWizard::CustomField.list_by(:klass, 'topic').length).to eq(1) end end - + it "is enabled if there are custom fields" do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save end expect(CustomWizard::CustomField.enabled?).to eq(true) end - + it "is not enabled if there are no custom fields" do expect(CustomWizard::CustomField.enabled?).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/field_spec.rb b/spec/components/custom_wizard/field_spec.rb index 295e5137..f6c2d68b 100644 --- a/spec/components/custom_wizard/field_spec.rb +++ b/spec/components/custom_wizard/field_spec.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::Field do - before do + before do CustomWizard::Field.register( 'location', 'discourse-locations', @@ -11,20 +12,20 @@ describe CustomWizard::Field do } ) end - - it "registers custom field types" do + + it "registers custom field types" do expect(CustomWizard::Field.types[:location].present?).to eq(true) end - + it "allows custom field types to set default attributes" do expect( CustomWizard::Field.types[:location][:prefill] ).to eq({ "coordinates": [35.3082, 149.1244] }) end - + it "registers custom field assets" do expect( CustomWizard::Field.require_assets['discourse-locations'] ).to eq(['components', 'helpers', 'lib', 'stylesheets', 'templates']) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/log_spec.rb b/spec/components/custom_wizard/log_spec.rb index d68c6ba1..30fd0173 100644 --- a/spec/components/custom_wizard/log_spec.rb +++ b/spec/components/custom_wizard/log_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::Log do @@ -6,22 +7,22 @@ describe CustomWizard::Log do CustomWizard::Log.create("Second log message") CustomWizard::Log.create("Third log message") end - + it "creates logs" do expect( CustomWizard::Log.list.length ).to eq(3) end - + it "lists logs by time created" do expect( CustomWizard::Log.list.first.message ).to eq("Third log message") end - + it "paginates logs" do expect( CustomWizard::Log.list(0, 2).length ).to eq(2) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/mapper_spec.rb b/spec/components/custom_wizard/mapper_spec.rb index bb87a623..3b993b4b 100644 --- a/spec/components/custom_wizard/mapper_spec.rb +++ b/spec/components/custom_wizard/mapper_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::Mapper do @@ -40,7 +41,7 @@ describe CustomWizard::Mapper do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/mapper/data.json" ).read) } - + it "maps values" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment'], @@ -48,7 +49,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq([13]) end - + it "maps associations" do association = CustomWizard::Mapper.new( inputs: inputs['association'], @@ -58,7 +59,7 @@ describe CustomWizard::Mapper do expect(association.length).to eq(3) expect(association.first[:value]).to eq("Choice 1") end - + context "conditional mapping" do it "maps when the condition is met" do expect(CustomWizard::Mapper.new( @@ -67,7 +68,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("true") end - + it "does not map when the condition is not met" do expect(CustomWizard::Mapper.new( inputs: inputs['conditional'], @@ -75,7 +76,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(nil) end - + it "maps when multiple conditions are met" do expect(CustomWizard::Mapper.new( inputs: inputs['conditional_multiple_pairs'], @@ -83,9 +84,11 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("true") end - + it "does not map when one of multiple conditions are not met" do user1.email = "angus@other-email.com" + user1.save + expect(CustomWizard::Mapper.new( inputs: inputs['conditional_multiple_pairs'], data: data, @@ -93,7 +96,7 @@ describe CustomWizard::Mapper do ).perform).to eq(nil) end end - + it "validates valid data" do expect(CustomWizard::Mapper.new( inputs: inputs['validation'], @@ -101,7 +104,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq(true) end - + it "does not validate invalid data" do data["input_2"] = "value 3" expect(CustomWizard::Mapper.new( @@ -110,7 +113,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq(false) end - + it "maps text fields" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment_text'], @@ -118,7 +121,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("Value") end - + it "maps user fields" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment_user_field'], @@ -126,7 +129,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("Angus") end - + it "maps user field options" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment_user_field_options'], @@ -134,7 +137,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq(["a", "b", "c"]) end - + it "maps wizard fields" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment_wizard_field'], @@ -142,7 +145,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("value 1") end - + it "maps wizard actions" do expect(CustomWizard::Mapper.new( inputs: inputs['assignment_wizard_action'], @@ -150,7 +153,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("value 2") end - + it "interpolates user fields" do expect(CustomWizard::Mapper.new( inputs: inputs['interpolate_user_field'], @@ -158,7 +161,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("Name: Angus") end - + it "interpolates wizard fields" do expect(CustomWizard::Mapper.new( inputs: inputs['interpolate_wizard_field'], @@ -166,7 +169,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("Input 1: value 1") end - + it "interpolates date" do expect(CustomWizard::Mapper.new( inputs: inputs['interpolate_timestamp'], @@ -174,7 +177,7 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq("Time: #{Time.now.strftime("%B %-d, %Y")}") end - + it "handles greater than pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['greater_than_pair'], @@ -187,7 +190,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(false) end - + it "handles less than pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['less_than_pair'], @@ -200,7 +203,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(true) end - + it "handles greater than or equal pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['greater_than_or_equal_pair'], @@ -213,7 +216,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(true) end - + it "handles less than or equal pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['less_than_or_equal_pair'], @@ -226,7 +229,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(true) end - + it "handles regex pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['regex_pair'], @@ -239,7 +242,7 @@ describe CustomWizard::Mapper do user: user2 ).perform).to eq(false) end - + it "handles shorthand pairs" do expect(CustomWizard::Mapper.new( inputs: inputs['shorthand_pair'], @@ -247,4 +250,4 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/template_spec.rb b/spec/components/custom_wizard/template_spec.rb index 7a862c63..fb76e0c4 100644 --- a/spec/components/custom_wizard/template_spec.rb +++ b/spec/components/custom_wizard/template_spec.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::Template do fab!(:user) { Fabricate(:user) } - + let(:template_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" @@ -13,11 +14,11 @@ describe CustomWizard::Template do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard/permitted.json" ).read) } - + before do CustomWizard::Template.save(template_json, skip_jobs: true) end - + it "saves wizard templates" do expect( PluginStoreRow.exists?( @@ -26,51 +27,51 @@ describe CustomWizard::Template do ) ).to eq(true) end - + it "finds wizard templates" do expect( CustomWizard::Template.find('super_mega_fun_wizard')['id'] ).to eq('super_mega_fun_wizard') end - + it "removes wizard templates" do CustomWizard::Template.remove('super_mega_fun_wizard') expect( CustomWizard::Template.find('super_mega_fun_wizard') ).to eq(nil) end - + it "checks for wizard template existence" do expect( CustomWizard::Template.exists?('super_mega_fun_wizard') ).to eq(true) end - + context "wizard template list" do before do template_json_2 = template_json.dup template_json_2["id"] = 'super_mega_fun_wizard_2' template_json_2["permitted"] = permitted_json['permitted'] CustomWizard::Template.save(template_json_2, skip_jobs: true) - + template_json_3 = template_json.dup template_json_3["id"] = 'super_mega_fun_wizard_3' template_json_3["after_signup"] = true CustomWizard::Template.save(template_json_3, skip_jobs: true) end - + it "works" do expect( CustomWizard::Template.list.length ).to eq(3) end - + it "can be filtered by wizard settings" do expect( CustomWizard::Template.list(setting: "after_signup").length ).to eq(1) end - + it "can be ordered" do expect( CustomWizard::Template.list( @@ -79,30 +80,30 @@ describe CustomWizard::Template do ).to eq('super_mega_fun_wizard_2') end end - + context "after time setting" do before do freeze_time Time.now @scheduled_time = (Time.now + 3.hours).iso8601 - + @after_time_template = template_json.dup @after_time_template["after_time"] = true @after_time_template["after_time_scheduled"] = @scheduled_time end - - it 'if enabled queues jobs after wizard is saved' do + + it 'if enabled queues jobs after wizard is saved' do expect_enqueued_with(job: :set_after_time_wizard, at: Time.parse(@scheduled_time).utc) do CustomWizard::Template.save(@after_time_template) end end - + it 'if disabled clears jobs after wizard is saved' do CustomWizard::Template.save(@after_time_template) @after_time_template['after_time'] = false - + expect_not_enqueued_with(job: :set_after_time_wizard) do CustomWizard::Template.save(@after_time_template) end end end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/template_validator_spec.rb b/spec/components/custom_wizard/template_validator_spec.rb index 1f941675..c8ce915a 100644 --- a/spec/components/custom_wizard/template_validator_spec.rb +++ b/spec/components/custom_wizard/template_validator_spec.rb @@ -1,34 +1,35 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::TemplateValidator do fab!(:user) { Fabricate(:user) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read).with_indifferent_access } - + it "validates valid templates" do expect( CustomWizard::TemplateValidator.new(template).perform ).to eq(true) end - + it "invalidates templates without required attributes" do template.delete(:id) expect( CustomWizard::TemplateValidator.new(template).perform ).to eq(false) end - + it "invalidates templates with duplicate ids if creating a new template" do CustomWizard::Template.save(template) expect( CustomWizard::TemplateValidator.new(template, create: true).perform ).to eq(false) end - + it "validates after time settings" do template[:after_time] = true template[:after_time_scheduled] = (Time.now + 3.hours).iso8601 @@ -36,7 +37,7 @@ describe CustomWizard::TemplateValidator do CustomWizard::TemplateValidator.new(template).perform ).to eq(true) end - + it "invalidates invalid after time settings" do template[:after_time] = true template[:after_time_scheduled] = "not a time" @@ -44,4 +45,4 @@ describe CustomWizard::TemplateValidator do CustomWizard::TemplateValidator.new(template).perform ).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/update_validator_spec.rb b/spec/components/custom_wizard/update_validator_spec.rb index 4c854dcd..81212b4b 100644 --- a/spec/components/custom_wizard/update_validator_spec.rb +++ b/spec/components/custom_wizard/update_validator_spec.rb @@ -1,46 +1,47 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::UpdateValidator do fab!(:user) { Fabricate(:user) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read).with_indifferent_access } - + before do CustomWizard::Template.save(template, skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - + def perform_validation(step_id, submission) wizard = CustomWizard::Builder.new(@template[:id], user).build updater = wizard.create_updater(step_id, submission) updater.validate updater end - + it 'applies min length to text type fields' do min_length = 3 - + @template[:steps][0][:fields][0][:min_length] = min_length @template[:steps][0][:fields][1][:min_length] = min_length @template[:steps][0][:fields][2][:min_length] = min_length - + CustomWizard::Template.save(@template) - + updater = perform_validation('step_1', step_1_field_1: 'Te') expect( updater.errors.messages[:step_1_field_1].first ).to eq(I18n.t('wizard.field.too_short', label: 'Text', min: min_length)) - - updater = perform_validation('step_1', step_1_field_2: 'Te') + + updater = perform_validation('step_1', step_1_field_2: 'Te') expect( updater.errors.messages[:step_1_field_2].first ).to eq(I18n.t('wizard.field.too_short', label: 'Textarea', min: min_length)) - - updater = perform_validation('step_1', step_1_field_3: 'Te') + + updater = perform_validation('step_1', step_1_field_3: 'Te') expect( updater.errors.messages[:step_1_field_3].first ).to eq(I18n.t('wizard.field.too_short', label: 'Composer', min: min_length)) @@ -100,35 +101,35 @@ describe CustomWizard::UpdateValidator do updater = perform_validation('step_2', step_2_field_5: 'false') expect(updater.submission['step_2_field_5']).to eq(false) end - + it 'requires required fields' do @template[:steps][0][:fields][1][:required] = true CustomWizard::Template.save(@template) - - updater = perform_validation('step_1', step_1_field_2: nil) + + updater = perform_validation('step_1', step_1_field_2: nil) expect( updater.errors.messages[:step_1_field_2].first - ).to eq(I18n.t('wizard.field.required', label: 'Textarea')) + ).to eq(I18n.t('wizard.field.required', label: 'Textarea')) end - + it 'validates url fields' do updater = perform_validation('step_2', step_2_field_6: 'https://discourse.com') expect( updater.errors.messages[:step_2_field_6].first ).to eq(nil) end - + it 'does not validate url fields with non-url inputs' do updater = perform_validation('step_2', step_2_field_6: 'discourse') expect( updater.errors.messages[:step_2_field_6].first ).to eq(I18n.t('wizard.field.not_url', label: 'Url')) end - + it 'validates empty url fields' do updater = perform_validation('step_2', step_2_field_6: '') expect( updater.errors.messages[:step_2_field_6].first ).to eq(nil) end -end \ No newline at end of file +end diff --git a/spec/components/custom_wizard/wizard_spec.rb b/spec/components/custom_wizard/wizard_spec.rb index 93ac7972..c348fc6b 100644 --- a/spec/components/custom_wizard/wizard_spec.rb +++ b/spec/components/custom_wizard/wizard_spec.rb @@ -1,34 +1,35 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::Wizard do fab!(:user) { Fabricate(:user) } - fab!(:trusted_user) { Fabricate(:user, trust_level: TrustLevel[3])} - fab!(:admin_user) { Fabricate(:user, admin: true)} - + fab!(:trusted_user) { Fabricate(:user, trust_level: TrustLevel[3]) } + fab!(:admin_user) { Fabricate(:user, admin: true) } + let(:template_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) } - + let(:permitted_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard/permitted.json" ).read) } - + before do Group.refresh_automatic_group!(:trust_level_3) - + @permitted_template = template_json.dup @permitted_template["permitted"] = permitted_json["permitted"] - + @wizard = CustomWizard::Wizard.new(template_json, user) template_json['steps'].each do |step_template| @wizard.append_step(step_template['id']) end end - + def progress_step(step_id, acting_user: user, wizard: @wizard) UserHistory.create( action: UserHistory.actions[:custom_wizard_step], @@ -36,25 +37,25 @@ describe CustomWizard::Wizard do context: wizard.id, subject: step_id ) - end - + end + it "appends steps from a template" do expect(@wizard.steps.length).to eq(3) end - + it "determines the user's current step" do expect(@wizard.start.id).to eq('step_1') progress_step('step_1') expect(@wizard.start.id).to eq('step_2') end - + it "creates a step updater" do expect( @wizard.create_updater('step_1', step_1_field_1: "Text input") .class ).to eq(CustomWizard::StepUpdater) end - + it "determines whether a wizard is unfinished" do expect(@wizard.unfinished?).to eq(true) progress_step("step_1") @@ -64,7 +65,7 @@ describe CustomWizard::Wizard do progress_step("step_3") expect(@wizard.unfinished?).to eq(false) end - + it "determines whether a wizard has been completed by a user" do expect(@wizard.completed?).to eq(false) progress_step("step_1") @@ -72,101 +73,101 @@ describe CustomWizard::Wizard do progress_step("step_3") expect(@wizard.completed?).to eq(true) end - + it "is not completed if steps submitted before after time" do progress_step("step_1") progress_step("step_2") progress_step("step_3") - + template_json['after_time'] = true template_json['after_time_scheduled'] = Time.now + 3.hours - + wizard = CustomWizard::Wizard.new(template_json, user) - + expect(wizard.completed?).to eq(false) end - + it "permits admins" do expect( CustomWizard::Wizard.new(@permitted_template, admin_user).permitted? ).to eq(true) end - + it "permits permitted users" do expect( CustomWizard::Wizard.new(@permitted_template, trusted_user).permitted? ).to eq(true) end - + it "does not permit unpermitted users" do expect( CustomWizard::Wizard.new(@permitted_template, user).permitted? ).to eq(false) end - + it "does not let an unpermitted user access a wizard" do expect( CustomWizard::Wizard.new(@permitted_template, user).can_access? ).to eq(false) end - + it "lets a permitted user access an incomplete wizard" do expect( CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access? ).to eq(true) end - + it "lets a permitted user access a complete wizard with multiple submissions" do progress_step("step_1", acting_user: trusted_user) progress_step("step_2", acting_user: trusted_user) progress_step("step_3", acting_user: trusted_user) - + expect( CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access? ).to eq(true) end - + it "does not let an unpermitted user access a complete wizard without multiple submissions" do progress_step("step_1", acting_user: trusted_user) progress_step("step_2", acting_user: trusted_user) progress_step("step_3", acting_user: trusted_user) - + @permitted_template['multiple_submissions'] = false - + expect( CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access? ).to eq(false) end - + it "lists the site groups" do expect(@wizard.groups.length).to eq(8) end - + it "lists the site categories" do expect(@wizard.categories.length).to eq(1) end - + 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') end - + it "lists the user's submissions" do expect(@wizard.submissions.length).to eq(1) end - + it "returns the user's current submission" do expect(@wizard.current_submission['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' @@ -180,32 +181,32 @@ describe CustomWizard::Wizard do context do before do CustomWizard::Template.save(@permitted_template, skip_jobs: true) - + template_json_2 = template_json.dup template_json_2["id"] = 'super_mega_fun_wizard_2' template_json_2["prompt_completion"] = true CustomWizard::Template.save(template_json_2, skip_jobs: true) - + template_json_3 = template_json.dup template_json_3["id"] = 'super_mega_fun_wizard_3' template_json_3["after_signup"] = true template_json_3["prompt_completion"] = true CustomWizard::Template.save(template_json_3, skip_jobs: true) end - + it "lists wizards the user can see" do expect(CustomWizard::Wizard.list(user).length).to eq(2) expect(CustomWizard::Wizard.list(trusted_user).length).to eq(3) end - + it "returns the first after signup wizard" do expect(CustomWizard::Wizard.after_signup(user).id).to eq('super_mega_fun_wizard_3') end - + it "lists prompt completion wizards" do expect(CustomWizard::Wizard.prompt_completion(user).length).to eq(2) end - + it "prompt completion does not include wizards user has completed" do wizard_2 = CustomWizard::Wizard.new(CustomWizard::Template.find('super_mega_fun_wizard_2'), user) progress_step("step_1", wizard: wizard_2) @@ -214,7 +215,7 @@ describe CustomWizard::Wizard do expect(CustomWizard::Wizard.prompt_completion(user).length).to eq(1) end end - + 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) @@ -222,7 +223,7 @@ describe CustomWizard::Wizard do trusted_user.custom_fields['redirect_to_wizard'] ).to eq("super_mega_fun_wizard") end - + 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) @@ -230,4 +231,4 @@ describe CustomWizard::Wizard do trusted_user.custom_fields['redirect_to_wizard'] ).to eq(nil) end -end \ No newline at end of file +end diff --git a/spec/extensions/custom_field_extensions_spec.rb b/spec/extensions/custom_field_extensions_spec.rb index 5abb0bd8..f0ce32f5 100644 --- a/spec/extensions/custom_field_extensions_spec.rb +++ b/spec/extensions/custom_field_extensions_spec.rb @@ -8,110 +8,110 @@ describe "custom field extensions" do fab!(:category) { Fabricate(:category) } fab!(:group) { Fabricate(:group) } fab!(:user) { Fabricate(:user) } - + let(:custom_field_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json" ).read) } - + before do custom_field_json['custom_fields'].each do |field_json| custom_field = CustomWizard::CustomField.new(nil, field_json) custom_field.save end end - + context "topic" do it "registers topic custom fields" do topic expect(Topic.get_custom_field_type("topic_field_1")).to eq(:boolean) end - + it "adds topic custom fields to the topic_view serializer" do topic.custom_fields["topic_field_1"] = true topic.save_custom_fields(true) - + serializer = TopicViewSerializer.new( TopicView.new(topic.id, user), scope: Guardian.new(user), root: false ).as_json - + expect(serializer[:topic_field_1]).to eq(true) end - + it "adds topic custom fields to the topic_list_item serializer" do topic.custom_fields["topic_field_1"] = true topic.save_custom_fields(true) - + serializer = TopicListItemSerializer.new( topic, scope: Guardian.new(user), root: false ).as_json - + expect(serializer[:topic_field_1]).to eq(true) end end - + context "post" do it "registers post custom fields" do post expect(Post.get_custom_field_type("post_field_1")).to eq(:integer) end - + it "adds post custom fields to the post serializer" do post.custom_fields["post_field_1"] = 7 post.save_custom_fields(true) - + serializer = PostSerializer.new( post, scope: Guardian.new(user), root: false ).as_json - + expect(serializer[:post_field_1]).to eq(7) end end - + context "category" do it "registers category custom fields" do category expect(Category.get_custom_field_type("category_field_1")).to eq(:json) end - + it "adds category custom fields to the basic category serializer" do category.custom_fields["category_field_1"] = { a: 1, b: 2 }.to_json category.save_custom_fields(true) - + serializer = BasicCategorySerializer.new( category, scope: Guardian.new(user), root: false ).as_json - + expect(serializer[:category_field_1]).to eq({ a: 1, b: 2 }.to_json) end end - + context "group" do it "registers group custom fields" do group expect(Group.get_custom_field_type("group_field_1")).to eq(:string) end - + it "adds group custom fields to the basic group serializer" do group.custom_fields["group_field_1"] = "Hello" group.save_custom_fields(true) - + serializer = BasicGroupSerializer.new( group, scope: Guardian.new(user), root: false ).as_json - + expect(serializer[:group_field_1]).to eq("Hello") end end -end \ No newline at end of file +end diff --git a/spec/extensions/extra_locales_controller_spec.rb b/spec/extensions/extra_locales_controller_spec.rb index 6d6374fd..91a4e8c3 100644 --- a/spec/extensions/extra_locales_controller_spec.rb +++ b/spec/extensions/extra_locales_controller_spec.rb @@ -1,59 +1,60 @@ +# frozen_string_literal: true require_relative '../plugin_helper' describe ExtraLocalesControllerCustomWizard, type: :request do let(:new_user) { Fabricate(:user, trust_level: TrustLevel[0]) } let(:staff_user) { Fabricate(:moderator) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) } - + let(:permitted) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard/permitted.json" ).read) } - + before do CustomWizard::Template.save(template, skip_jobs: true) end - + before do js_hash = ExtraLocalesController.bundle_js_hash("wizard") @locale_url = "#{Discourse.base_path}/extra-locales/wizard?v=#{js_hash}" end - + it "generates the correct wizard locale url" do expect(ExtraLocalesController.url("wizard")).to eq(@locale_url) end - + it "returns wizard locales when requested by user in wizard" do sign_in(new_user) - + get @locale_url, headers: { 'REFERER' => "/w/super-mega-fun-wizard" } expect(response.status).to eq(200) end - + it "return wizard locales if user cant access wizard" do template[:permitted] = permitted["permitted"] CustomWizard::Template.save(template.as_json) - + sign_in(new_user) get @locale_url, headers: { 'REFERER' => "/w/super-mega-fun-wizard" } expect(response.status).to eq(200) end - + it "doesnt return wizard locales to non-staff when requested outside of wizard" do sign_in(new_user) get @locale_url expect(response.status).to eq(403) end - + it "returns wizard locales to staff when requested outside of wizard" do sign_in(staff_user) get @locale_url expect(response.status).to eq(200) end -end \ No newline at end of file +end diff --git a/spec/extensions/invites_controller_spec.rb b/spec/extensions/invites_controller_spec.rb index affd3760..ee75500e 100644 --- a/spec/extensions/invites_controller_spec.rb +++ b/spec/extensions/invites_controller_spec.rb @@ -1,24 +1,24 @@ +# frozen_string_literal: true require_relative '../plugin_helper' describe InvitesControllerCustomWizard, type: :request do fab!(:topic) { Fabricate(:topic) } - let(:invite) do - Invite.invite_by_email("angus@email.com", topic.user, topic) - end + let(:invite) { Invite.generate(topic.user, email: "angus@mcleod.org", topic: topic) } + let(:template) do JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) end - + before do @controller = InvitesController.new end - + it "redirects a user to wizard after invite if after signup is enabled" do template['after_signup'] = true CustomWizard::Template.save(template, skip_jobs: true) put "/invites/show/#{invite.invite_key}.json" expect(response.parsed_body["redirect_to"]).to eq("/w/super-mega-fun-wizard") - end -end \ No newline at end of file + end +end diff --git a/spec/extensions/users_controller_spec.rb b/spec/extensions/users_controller_spec.rb index dccee66b..f4ba8e51 100644 --- a/spec/extensions/users_controller_spec.rb +++ b/spec/extensions/users_controller_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../plugin_helper' describe CustomWizardUsersController, type: :request do @@ -6,16 +7,16 @@ describe CustomWizardUsersController, type: :request do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) end - + before do @controller = UsersController.new end - + it "redirects a user to wizard after sign up if after signup is enabled" do template['after_signup'] = true CustomWizard::Template.save(template, skip_jobs: true) sign_in(Fabricate(:user)) get "/u/account-created" expect(response).to redirect_to("/w/super-mega-fun-wizard") - end -end \ No newline at end of file + end +end diff --git a/spec/extensions/wizard_field_spec.rb b/spec/extensions/wizard_field_spec.rb index 63cbb249..370c25e7 100644 --- a/spec/extensions/wizard_field_spec.rb +++ b/spec/extensions/wizard_field_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../plugin_helper' describe CustomWizardFieldExtension do @@ -6,7 +7,7 @@ describe CustomWizardFieldExtension do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/field/field.json" ).read).with_indifferent_access end - + it "adds custom field attributes" do field = Wizard::Field.new(field_hash) expect(field.id).to eq("field_id") @@ -17,5 +18,5 @@ describe CustomWizardFieldExtension do expect(field.key).to eq("field.locale.key") expect(field.type).to eq("field_type") expect(field.content).to eq([]) - end -end \ No newline at end of file + end +end diff --git a/spec/extensions/wizard_step_spec.rb b/spec/extensions/wizard_step_spec.rb index 2075a419..1a9cc0e5 100644 --- a/spec/extensions/wizard_step_spec.rb +++ b/spec/extensions/wizard_step_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../plugin_helper' describe CustomWizardStepExtension do @@ -6,9 +7,9 @@ describe CustomWizardStepExtension do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/step/step.json" ).read).with_indifferent_access end - + it "adds custom step attributes" do - step = Wizard::Step.new(step_hash[:id]) + step = Wizard::Step.new(step_hash[:id]) [ :title, :description, @@ -19,5 +20,5 @@ describe CustomWizardStepExtension do step.send("#{attr.to_s}=", step_hash[attr]) expect(step.send(attr)).to eq(step_hash[attr]) end - end -end \ No newline at end of file + end +end diff --git a/spec/jobs/clear_after_time_wizard_spec.rb b/spec/jobs/clear_after_time_wizard_spec.rb index 16e30c2d..935036a3 100644 --- a/spec/jobs/clear_after_time_wizard_spec.rb +++ b/spec/jobs/clear_after_time_wizard_spec.rb @@ -6,7 +6,7 @@ describe Jobs::ClearAfterTimeWizard do fab!(:user1) { Fabricate(:user) } fab!(:user2) { Fabricate(:user) } fab!(:user3) { Fabricate(:user) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" @@ -17,20 +17,20 @@ describe Jobs::ClearAfterTimeWizard do after_time_template = template.dup after_time_template["after_time"] = true after_time_template["after_time_scheduled"] = (Time.now + 3.hours).iso8601 - + CustomWizard::Template.save(after_time_template) - + Jobs::SetAfterTimeWizard.new.execute(wizard_id: 'super_mega_fun_wizard') - + expect( UserCustomField.where( name: 'redirect_to_wizard', value: 'super_mega_fun_wizard' ).length ).to eq(3) - + described_class.new.execute(wizard_id: 'super_mega_fun_wizard') - + expect( UserCustomField.where(" name = 'redirect_to_wizard' AND @@ -38,4 +38,4 @@ describe Jobs::ClearAfterTimeWizard do ").exists? ).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/jobs/set_after_time_wizard_spec.rb b/spec/jobs/set_after_time_wizard_spec.rb index 81749051..35576f01 100644 --- a/spec/jobs/set_after_time_wizard_spec.rb +++ b/spec/jobs/set_after_time_wizard_spec.rb @@ -6,7 +6,7 @@ describe Jobs::SetAfterTimeWizard do fab!(:user1) { Fabricate(:user) } fab!(:user2) { Fabricate(:user) } fab!(:user3) { Fabricate(:user) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" @@ -17,21 +17,21 @@ describe Jobs::SetAfterTimeWizard do after_time_template = template.dup after_time_template["after_time"] = true after_time_template["after_time_scheduled"] = (Time.now + 3.hours).iso8601 - + CustomWizard::Template.save(after_time_template) - + messages = MessageBus.track_publish("/redirect_to_wizard") do described_class.new.execute(wizard_id: 'super_mega_fun_wizard') end - + expect( UserCustomField.where( name: 'redirect_to_wizard', value: 'super_mega_fun_wizard' ).length ).to eq(3) - + expect(messages.first.data).to eq("super_mega_fun_wizard") - expect(messages.first.user_ids).to match_array([user1.id,user2.id,user3.id]) + expect(messages.first.user_ids).to match_array([user1.id, user2.id, user3.id]) end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb b/spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb index 2eee457e..e006e65a 100644 --- a/spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb @@ -1,14 +1,15 @@ +# frozen_string_literal: true require_relative '../../../plugin_helper' describe CustomWizard::AdminCustomFieldsController do fab!(:admin_user) { Fabricate(:user, admin: true) } - + let(:custom_field_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json" ).read) } - + before do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save @@ -20,12 +21,12 @@ describe CustomWizard::AdminCustomFieldsController do get "/admin/wizards/custom-fields.json" expect(response.parsed_body.length).to eq(4) end - + it "saves custom fields" do topic_field = CustomWizard::CustomField.find_by_name('topic_field_1') topic_field_json = topic_field.as_json topic_field_json['type'] = 'string' - + put "/admin/wizards/custom-fields.json", params: { custom_field: topic_field_json } @@ -34,7 +35,7 @@ describe CustomWizard::AdminCustomFieldsController do CustomWizard::CustomField.find_by_name('topic_field_1').type ).to eq('string') end - + it "destroys custom fields" do topic_field = custom_field_json['custom_fields'][0] delete "/admin/wizards/custom-fields/#{topic_field["name"]}.json" @@ -43,4 +44,4 @@ describe CustomWizard::AdminCustomFieldsController do CustomWizard::CustomField.exists?('topic_field_1') ).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/admin/logs_controller_spec.rb b/spec/requests/custom_wizard/admin/logs_controller_spec.rb index 2eefb299..28b7d785 100644 --- a/spec/requests/custom_wizard/admin/logs_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/logs_controller_spec.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true require_relative '../../../plugin_helper' describe CustomWizard::AdminLogsController do fab!(:admin_user) { Fabricate(:user, admin: true) } - + before do CustomWizard::Log.create("First log message") CustomWizard::Log.create("Second log message") @@ -14,9 +15,9 @@ describe CustomWizard::AdminLogsController do get "/admin/wizards/logs.json" expect(response.parsed_body.length).to eq(3) end - + it "paginates" do get "/admin/wizards/logs.json", params: { page: 1, limit: 2 } expect(response.parsed_body.length).to eq(1) end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/admin/manager_controller_spec.rb b/spec/requests/custom_wizard/admin/manager_controller_spec.rb index 33113c1b..87c980f2 100644 --- a/spec/requests/custom_wizard/admin/manager_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/manager_controller_spec.rb @@ -1,17 +1,18 @@ +# frozen_string_literal: true require_relative '../../../plugin_helper' describe CustomWizard::AdminManagerController do fab!(:admin_user) { Fabricate(:user, admin: true) } - + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) } - + before do sign_in(admin_user) - + template_2 = template.dup template_2["id"] = 'super_mega_fun_wizard_2' @@ -20,17 +21,17 @@ describe CustomWizard::AdminManagerController do template_3["after_signup"] = true @template_array = [template, template_2, template_3] - + FileUtils.mkdir_p(file_from_fixtures_tmp_folder) unless Dir.exists?(file_from_fixtures_tmp_folder) @tmp_file_path = File.join(file_from_fixtures_tmp_folder, SecureRandom.hex << 'wizards.json') File.write(@tmp_file_path, @template_array.to_json) end - + it 'exports all the wizard templates' do @template_array.each do |template| CustomWizard::Template.save(template, skip_jobs: true) end - + get '/admin/wizards/manager/export.json', params: { wizard_ids: [ 'super_mega_fun_wizard', @@ -38,38 +39,38 @@ describe CustomWizard::AdminManagerController do 'super_mega_fun_wizard_3' ] } - + expect(response.status).to eq(200) expect(response.parsed_body).to match_array(@template_array) end - + context "import" do it "works" do templates = @template_array.map { |t| t.slice('id', 'name') } - - post '/admin/wizards/manager/import.json', params: { - file: fixture_file_upload(File.open(@tmp_file_path)) + + post '/admin/wizards/manager/import.json', params: { + file: fixture_file_upload(File.open(@tmp_file_path)) } - + expect(response.status).to eq(200) expect(response.parsed_body['imported']).to match_array(templates) - expect(CustomWizard::Template.list.map {|t| t.slice('id', 'name') }).to match_array(templates) + expect(CustomWizard::Template.list.map { |t| t.slice('id', 'name') }).to match_array(templates) end - + it 'rejects a template with the same id as a saved template' do templates = @template_array.map { |t| t.slice('id', 'name') } - - post '/admin/wizards/manager/import.json', params: { - file: fixture_file_upload(File.open(@tmp_file_path)) + + post '/admin/wizards/manager/import.json', params: { + file: fixture_file_upload(File.open(@tmp_file_path)) } - + expect(response.status).to eq(200) expect(response.parsed_body['imported']).to match_array(templates) - - post '/admin/wizards/manager/import.json', params: { - file: fixture_file_upload(File.open(@tmp_file_path)) + + post '/admin/wizards/manager/import.json', params: { + file: fixture_file_upload(File.open(@tmp_file_path)) } - + expect(response.status).to eq(200) expect(response.parsed_body['failures']).to match_array( @template_array.map do |t| @@ -81,14 +82,14 @@ describe CustomWizard::AdminManagerController do ) end end - + it 'destroys wizard templates' do templates = @template_array.map { |t| t.slice('id', 'name') } - + @template_array.each do |template| CustomWizard::Template.save(template, skip_jobs: true) end - + delete '/admin/wizards/manager/destroy.json', params: { wizard_ids: [ 'super_mega_fun_wizard', @@ -96,9 +97,9 @@ describe CustomWizard::AdminManagerController do 'super_mega_fun_wizard_3' ] } - + expect(response.status).to eq(200) expect(response.parsed_body['destroyed']).to match_array(templates) expect(CustomWizard::Template.list.length).to eq(0) end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/admin/submissions_controller_spec.rb b/spec/requests/custom_wizard/admin/submissions_controller_spec.rb index 9edb131b..f63eead5 100644 --- a/spec/requests/custom_wizard/admin/submissions_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/submissions_controller_spec.rb @@ -1,16 +1,17 @@ +# frozen_string_literal: true require_relative '../../../plugin_helper' describe CustomWizard::AdminSubmissionsController do - fab!(:admin_user) {Fabricate(:user, admin: true)} - fab!(:user1) {Fabricate(:user)} - fab!(:user2) {Fabricate(:user)} - + fab!(:admin_user) { Fabricate(:user, admin: true) } + fab!(:user1) { Fabricate(:user) } + fab!(:user2) { Fabricate(:user) } + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) } - + before do CustomWizard::Template.save(template, skip_jobs: true) CustomWizard::Wizard.set_submissions(template['id'], user1, @@ -27,19 +28,19 @@ describe CustomWizard::AdminSubmissionsController do expect(response.parsed_body.length).to eq(1) expect(response.parsed_body.first['id']).to eq(template['id']) 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 "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) end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/admin/wizard_controller_spec.rb b/spec/requests/custom_wizard/admin/wizard_controller_spec.rb index 13067acd..82aa4fc5 100644 --- a/spec/requests/custom_wizard/admin/wizard_controller_spec.rb +++ b/spec/requests/custom_wizard/admin/wizard_controller_spec.rb @@ -1,29 +1,30 @@ +# frozen_string_literal: true require_relative '../../../plugin_helper' describe CustomWizard::AdminWizardController do - fab!(:admin_user) {Fabricate(:user, admin: true)} - fab!(:user1) {Fabricate(:user)} - fab!(:user2) {Fabricate(:user)} - + fab!(:admin_user) { Fabricate(:user, admin: true) } + fab!(:user1) { Fabricate(:user) } + fab!(:user2) { Fabricate(:user) } + let(:template) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json" ).read) } - + before do CustomWizard::Template.save(template, skip_jobs: true) - + template_2 = template.dup template_2["id"] = 'super_mega_fun_wizard_2' template_2["permitted"] = template_2['permitted'] CustomWizard::Template.save(template_2, skip_jobs: true) - + template_3 = template.dup template_3["id"] = 'super_mega_fun_wizard_3' template_3["after_signup"] = true CustomWizard::Template.save(template_3, skip_jobs: true) - + sign_in(admin_user) end @@ -36,31 +37,31 @@ describe CustomWizard::AdminWizardController do response.parsed_body['field_types'].keys ).to eq(CustomWizard::Field.types.keys.map(&:to_s)) end - + it "returns a wizard template" do get "/admin/wizards/wizard/#{template['id']}.json" expect(response.parsed_body['id']).to eq(template['id']) expect(response.parsed_body['steps'].length).to eq(3) end - + it "removes wizard templates" do delete "/admin/wizards/wizard/#{template['id']}.json" expect(response.status).to eq(200) expect(CustomWizard::Template.exists?(template['id'])).to eq(false) end - + it "saves wizard templates" do template_updated = template.dup template_updated['name'] = "Super Mega Fun Wizard 2" template_updated['multiple_submissions'] = false template_updated['steps'][0]['fields'][0]['label'] = "Text 2" - + put "/admin/wizards/wizard/#{template['id']}.json", params: { wizard: template_updated } expect(response.status).to eq(200) - + updated_template = CustomWizard::Template.find('super_mega_fun_wizard') expect(updated_template['name']).to eq("Super Mega Fun Wizard 2") expect(updated_template['multiple_submissions']).to eq("false") expect(updated_template['steps'][0]['fields'][0]['label']).to eq("Text 2") end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/application_controller_spec.rb b/spec/requests/custom_wizard/application_controller_spec.rb index 866e75a9..f79db877 100644 --- a/spec/requests/custom_wizard/application_controller_spec.rb +++ b/spec/requests/custom_wizard/application_controller_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe ApplicationController do @@ -7,7 +8,7 @@ describe ApplicationController do username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3] - ) + ) } before do @@ -18,23 +19,23 @@ describe ApplicationController do skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - + context "with signed in user" do before do sign_in(user) end - + context "who is required to complete wizard" do before do user.custom_fields['redirect_to_wizard'] = 'super_mega_fun_wizard' user.save_custom_fields(true) end - + it "redirects if user is required to complete a wizard" do get "/" expect(response).to redirect_to("/w/super-mega-fun-wizard") end - + it "saves original destination of user" do get '/', headers: { 'REFERER' => "/t/2" } expect( @@ -43,7 +44,7 @@ describe ApplicationController do ).to eq("/t/2") end end - + context "who is not required to complete wizard" do it "does nothing" do get "/" @@ -51,11 +52,11 @@ describe ApplicationController do end end end - + context "with guest" do it "does nothing" do get "/" expect(response.status).to eq(200) end end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/custom_field_extensions_spec.rb b/spec/requests/custom_wizard/custom_field_extensions_spec.rb index b93e89d2..b991769a 100644 --- a/spec/requests/custom_wizard/custom_field_extensions_spec.rb +++ b/spec/requests/custom_wizard/custom_field_extensions_spec.rb @@ -8,88 +8,87 @@ describe "custom field extensions" do let!(:category) { Fabricate(:category) } let!(:user) { Fabricate(:user) } let!(:group) { Fabricate(:group, users: [user]) } - + let(:custom_field_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json" ).read) } - + before do custom_field_json['custom_fields'].each do |field_json| custom_field = CustomWizard::CustomField.new(nil, field_json) custom_field.save end end - + it "adds topic custom fields to the show topic response" do topic.custom_fields["topic_field_1"] = true topic.save_custom_fields(true) - + get "/t/#{topic.slug}/#{topic.id}.json" - + expect(response.status).to eq(200) expect(response.parsed_body["topic_field_1"]).to eq(true) end - + it "adds category custom fields to the show categories response" do category.custom_fields["category_field_1"] = { a: 1, b: 2 } category.save_custom_fields(true) - + get "/c/#{category.id}/show.json" - + expect(response.status).to eq(200) expect(response.parsed_body["category"]["category_field_1"]).to eq({ a: 1, b: 2 }.as_json) end - + it "adds group custom fields to the show group response" do group.custom_fields["group_field_1"] = "Group cf entry" group.save_custom_fields(true) - + sign_in(user) get "/groups/#{group.name}.json" expect(response.status).to eq(200) expect(response.parsed_body['group']['group_field_1']).to eq("Group cf entry") end - + it "adds post custom fields to the show post response" do post.custom_fields["post_field_1"] = 7 post.save_custom_fields(true) - + get "/posts/#{post.id}.json" - + expect(response.status).to eq(200) expect(response.parsed_body['post_field_1']).to eq(7) end - + context "preloaded" do it "preloads category custom fields on site categories" do Site.preloaded_category_custom_fields << "other_field" - + category.custom_fields["category_field_1"] = { a: 1, b: 2 } category.save_custom_fields(true) - + get "/site.json" expect(response.status).to eq(200) - + site_category = response.parsed_body['categories'].select { |c| c['id'] == category.id }.first expect(site_category["category_field_1"]).to eq({ a: 1, b: 2 }.as_json) end - + it "preloads group custom fields on group index" do Group.preloaded_custom_field_names << "other_field" - + group = Fabricate(:group) group.custom_fields["group_field_1"] = "Group cf entry" group.save_custom_fields(true) - + get "/groups.json" expect(response.status).to eq(200) - + group = response.parsed_body['groups'].select { |g| g['id'] == group.id }.first expect(group['group_field_1']).to eq("Group cf entry") end end end - \ No newline at end of file diff --git a/spec/requests/custom_wizard/steps_controller_spec.rb b/spec/requests/custom_wizard/steps_controller_spec.rb index a236fd82..dd3b52a1 100644 --- a/spec/requests/custom_wizard/steps_controller_spec.rb +++ b/spec/requests/custom_wizard/steps_controller_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::StepsController do @@ -7,7 +8,7 @@ describe CustomWizard::StepsController do username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3] - ) + ) } before do @@ -18,7 +19,7 @@ describe CustomWizard::StepsController do skip_jobs: true) sign_in(user) end - + it 'performs a step update' do put '/w/super-mega-fun-wizard/steps/step_1.json', params: { fields: { @@ -26,17 +27,17 @@ describe CustomWizard::StepsController do } } expect(response.status).to eq(200) - + wizard = CustomWizard::Builder.new("super_mega_fun_wizard", user).build expect(wizard.current_submission['step_1_field_1']).to eq("Text input") expect(wizard.start.id).to eq("step_2") end - + it "works if the step has no fields" do put '/w/super-mega-fun-wizard/steps/step_1.json' expect(response.status).to eq(200) - + wizard = CustomWizard::Builder.new("super_mega_fun_wizard", user).build expect(wizard.start.id).to eq("step_2") end -end \ No newline at end of file +end diff --git a/spec/requests/custom_wizard/wizard_controller_spec.rb b/spec/requests/custom_wizard/wizard_controller_spec.rb index 30032ecc..3e7ddd3d 100644 --- a/spec/requests/custom_wizard/wizard_controller_spec.rb +++ b/spec/requests/custom_wizard/wizard_controller_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative '../../plugin_helper' describe CustomWizard::WizardController do @@ -7,7 +8,7 @@ describe CustomWizard::WizardController do username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3] - ) + ) } before do @@ -19,40 +20,40 @@ describe CustomWizard::WizardController do @template = CustomWizard::Template.find("super_mega_fun_wizard") sign_in(user) end - + context 'plugin disabled' do before do SiteSetting.custom_wizard_enabled = false end - + it 'redirects to root' do get '/w/super-mega-fun-wizard', xhr: true expect(response).to redirect_to("/") end end - + it 'returns wizard' do get '/w/super-mega-fun-wizard.json' expect(response.parsed_body["id"]).to eq("super_mega_fun_wizard") end - + it 'returns missing message if no wizard exists' do get '/w/super-mega-fun-wizards.json' expect(response.parsed_body["error"]).to eq("We couldn't find a wizard at that address.") end - + it 'skips a wizard if user is allowed to skip' do put '/w/super-mega-fun-wizard/skip.json' expect(response.status).to eq(200) end - + it 'returns a no skip message if user is not allowed to skip' do @template['required'] = 'true' CustomWizard::Template.save(@template) put '/w/super-mega-fun-wizard/skip.json' expect(response.parsed_body['error']).to eq("Wizard can't be skipped") end - + it 'skip response contains a redirect_to if in users submissions' do CustomWizard::Wizard.set_submissions(@template['id'], user, redirect_to: '/t/2' @@ -60,4 +61,4 @@ describe CustomWizard::WizardController do put '/w/super-mega-fun-wizard/skip.json' expect(response.parsed_body['redirect_to']).to eq('/t/2') end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/basic_wizard_serializer_spec.rb b/spec/serializers/custom_wizard/basic_wizard_serializer_spec.rb index 90d5a3a7..bf575827 100644 --- a/spec/serializers/custom_wizard/basic_wizard_serializer_spec.rb +++ b/spec/serializers/custom_wizard/basic_wizard_serializer_spec.rb @@ -4,7 +4,7 @@ require_relative '../../plugin_helper' describe CustomWizard::BasicWizardSerializer do fab!(:user) { Fabricate(:user) } - + it 'should return basic wizard attributes' do CustomWizard::Template.save( JSON.parse(File.open( @@ -18,4 +18,4 @@ describe CustomWizard::BasicWizardSerializer do expect(json[:basic_wizard][:id]).to eq("super_mega_fun_wizard") expect(json[:basic_wizard][:name]).to eq("Super Mega Fun Wizard") end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/custom_field_serializer_spec.rb b/spec/serializers/custom_wizard/custom_field_serializer_spec.rb index e1a2d806..4f5ffd72 100644 --- a/spec/serializers/custom_wizard/custom_field_serializer_spec.rb +++ b/spec/serializers/custom_wizard/custom_field_serializer_spec.rb @@ -4,18 +4,18 @@ require_relative '../../plugin_helper' describe CustomWizard::CustomFieldSerializer do fab!(:user) { Fabricate(:user) } - + let(:custom_field_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json" ).read) } - + it 'should return custom field attributes' do custom_field_json['custom_fields'].each do |field_json| CustomWizard::CustomField.new(nil, field_json).save end - + json = CustomWizard::CustomFieldSerializer.new( CustomWizard::CustomField.find_by_name("topic_field_1"), scope: Guardian.new(user), @@ -24,6 +24,6 @@ describe CustomWizard::CustomFieldSerializer do expect(json[:name]).to eq("topic_field_1") expect(json[:klass]).to eq("topic") expect(json[:type]).to eq("boolean") - expect(json[:serializers]).to match_array(["topic_list_item","topic_view"]) + expect(json[:serializers]).to match_array(["topic_list_item", "topic_view"]) end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/log_serializer_spec.rb b/spec/serializers/custom_wizard/log_serializer_spec.rb index 42dea659..bde16199 100644 --- a/spec/serializers/custom_wizard/log_serializer_spec.rb +++ b/spec/serializers/custom_wizard/log_serializer_spec.rb @@ -4,16 +4,16 @@ require_relative '../../plugin_helper' describe CustomWizard::LogSerializer do fab!(:user) { Fabricate(:user) } - + it 'should return log attributes' do CustomWizard::Log.create("First log message") CustomWizard::Log.create("Second log message") - + json_array = ActiveModel::ArraySerializer.new( CustomWizard::Log.list(0), each_serializer: CustomWizard::LogSerializer - ).as_json + ).as_json expect(json_array.length).to eq(2) expect(json_array[0][:message]).to eq("Second log message") end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/wizard_field_serializer_spec.rb b/spec/serializers/custom_wizard/wizard_field_serializer_spec.rb index 73de1f6b..0fd7c9ec 100644 --- a/spec/serializers/custom_wizard/wizard_field_serializer_spec.rb +++ b/spec/serializers/custom_wizard/wizard_field_serializer_spec.rb @@ -13,7 +13,7 @@ describe CustomWizard::FieldSerializer do skip_jobs: true) @wizard = CustomWizard::Builder.new("super_mega_fun_wizard", user).build end - + it "should return basic field attributes" do json_array = ActiveModel::ArraySerializer.new( @wizard.steps.first.fields, @@ -24,7 +24,7 @@ describe CustomWizard::FieldSerializer do expect(json_array[0][:label]).to eq("

Text

") expect(json_array[0][:description]).to eq("Text field description.") end - + it "should return optional field attributes" do json_array = ActiveModel::ArraySerializer.new( @wizard.steps.second.fields, @@ -32,7 +32,7 @@ describe CustomWizard::FieldSerializer do scope: Guardian.new(user) ).as_json expect(json_array[0][:format]).to eq("YYYY-MM-DD") - expect(json_array[5][:file_types]).to eq(".jpg,.png") - expect(json_array[4][:number]).to eq(5) + expect(json_array[3][:number]).to eq(4) + expect(json_array[6][:file_types]).to eq(".jpg,.png") end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/wizard_serializer_spec.rb b/spec/serializers/custom_wizard/wizard_serializer_spec.rb index e142712f..2052639a 100644 --- a/spec/serializers/custom_wizard/wizard_serializer_spec.rb +++ b/spec/serializers/custom_wizard/wizard_serializer_spec.rb @@ -5,7 +5,7 @@ require_relative '../../plugin_helper' describe CustomWizard::WizardSerializer do fab!(:user) { Fabricate(:user) } fab!(:category) { Fabricate(:category) } - + let(:similar_topics_validation) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/field/validation/similar_topics.json" @@ -20,7 +20,7 @@ describe CustomWizard::WizardSerializer do skip_jobs: true) @template = CustomWizard::Template.find('super_mega_fun_wizard') end - + it 'should return the wizard attributes' do json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, @@ -31,7 +31,7 @@ describe CustomWizard::WizardSerializer do expect(json[:wizard][:background]).to eq("#333333") expect(json[:wizard][:required]).to eq(false) end - + it 'should return the wizard steps' do json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, @@ -39,7 +39,7 @@ describe CustomWizard::WizardSerializer do ).as_json expect(json[:wizard][:steps].length).to eq(3) end - + it "should return the wizard user attributes" do json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, @@ -49,19 +49,19 @@ describe CustomWizard::WizardSerializer do json[:wizard][:user] ).to eq(BasicUserSerializer.new(user, root: false).as_json) end - + it "should not return categories if there are no category fields" do @template[:steps][2][:fields].delete_at(2) CustomWizard::Template.save(@template) - + json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, scope: Guardian.new(user) ).as_json expect(json[:wizard][:categories].present?).to eq(false) expect(json[:wizard][:uncategorized_category_id].present?).to eq(false) - end - + end + it "should return categories if there is a category selector field" do json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, @@ -70,11 +70,11 @@ describe CustomWizard::WizardSerializer do expect(json[:wizard][:categories].present?).to eq(true) expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) end - + it "should return categories if there is a similar topics validation scoped to category(s)" do @template[:steps][0][:fields][0][:validations] = similar_topics_validation[:validations] CustomWizard::Template.save(@template) - + json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, scope: Guardian.new(user) @@ -82,7 +82,7 @@ describe CustomWizard::WizardSerializer do expect(json[:wizard][:categories].present?).to eq(true) expect(json[:wizard][:uncategorized_category_id].present?).to eq(true) end - + it 'should return groups if there is a group selector field' do json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, @@ -90,15 +90,15 @@ describe CustomWizard::WizardSerializer do ).as_json expect(json[:wizard][:groups].length).to eq(8) end - + it 'should not return groups if there is not a group selector field' do @template[:steps][2][:fields].delete_at(3) CustomWizard::Template.save(@template) - + json = CustomWizard::WizardSerializer.new( CustomWizard::Builder.new(@template[:id], user).build, scope: Guardian.new(user) ).as_json expect(json[:wizard][:groups].present?).to eq(false) end -end \ No newline at end of file +end diff --git a/spec/serializers/custom_wizard/wizard_step_serializer.rb b/spec/serializers/custom_wizard/wizard_step_serializer.rb index d4a35d5d..c2d82962 100644 --- a/spec/serializers/custom_wizard/wizard_step_serializer.rb +++ b/spec/serializers/custom_wizard/wizard_step_serializer.rb @@ -4,13 +4,13 @@ require_relative '../../plugin_helper' describe CustomWizard::StepSerializer do fab!(:user) { Fabricate(:user) } - + let(:required_data_json) { JSON.parse(File.open( "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/step/required_data.json" ).read) } - + before do CustomWizard::Template.save( JSON.parse(File.open( @@ -19,7 +19,7 @@ describe CustomWizard::StepSerializer do skip_jobs: true) @wizard = CustomWizard::Builder.new("super_mega_fun_wizard", user).build end - + it 'should return basic step attributes' do json_array = ActiveModel::ArraySerializer.new( @wizard.steps, @@ -29,7 +29,7 @@ describe CustomWizard::StepSerializer do expect(json_array[0][:wizard_step][:title]).to eq("Text") expect(json_array[0][:wizard_step][:description]).to eq("Text inputs!") end - + it 'should return fields' do json_array = ActiveModel::ArraySerializer.new( @wizard.steps, @@ -38,14 +38,14 @@ describe CustomWizard::StepSerializer do ).as_json expect(json_array[0][:wizard_step][:fields].length).to eq(4) end - + context 'with required data' do before do @template[:steps][0][:required_data] = required_data_json['required_data'] @template[:steps][0][:required_data_message] = required_data_json['required_data_message'] CustomWizard::Template.save(@template.as_json) end - + it 'should return permitted attributes' do json_array = ActiveModel::ArraySerializer.new( @wizard.steps, @@ -56,4 +56,4 @@ describe CustomWizard::StepSerializer do expect(json_array[0][:wizard_step][:permitted_message]).to eq("Missing required data") end end -end \ No newline at end of file +end