Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 01:10:28 +01:00
Apply rubcop and get tests pass (#76)
Dieser Commit ist enthalten in:
Ursprung
065bc17929
Commit
4edb40e526
91 geänderte Dateien mit 1070 neuen und 1006 gelöschten Zeilen
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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("/")
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
module CustomWizardStepExtension
|
||||
attr_accessor :title, :description, :key, :permitted, :permitted_message
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
module Jobs
|
||||
class ClearAfterTimeWizard < ::Jobs::Base
|
||||
sidekiq_options queue: 'critical'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
module Jobs
|
||||
class RefreshApiAccessToken < ::Jobs::Base
|
||||
def execute(args)
|
||||
|
|
|
@ -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 = []
|
||||
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::ActionResult
|
||||
attr_accessor :success, :handler, :output
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
module ::CustomWizard
|
||||
PLUGIN_NAME ||= 'custom_wizard'
|
||||
|
||||
|
||||
class Engine < ::Rails::Engine
|
||||
engine_name PLUGIN_NAME
|
||||
isolate_namespace CustomWizard
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class CustomWizard::RealtimeValidation
|
||||
cattr_accessor :types
|
||||
|
||||
|
||||
@@types ||= {
|
||||
similar_topics: {
|
||||
types: [:text],
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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)
|
||||
|
|
27
plugin.rb
27
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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::Api::AuthorizationSerializer < ::ApplicationSerializer
|
||||
attributes :auth_type,
|
||||
:auth_url,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::Api::BasicEndpointSerializer < ::ApplicationSerializer
|
||||
attributes :id,
|
||||
:name
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::Api::EndpointSerializer < ::ApplicationSerializer
|
||||
attributes :id,
|
||||
:name,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::ApiSerializer < ::ApplicationSerializer
|
||||
attributes :name,
|
||||
:title,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::BasicApiSerializer < ::ApplicationSerializer
|
||||
attributes :name,
|
||||
:title,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::BasicWizardSerializer < ::ApplicationSerializer
|
||||
attributes :id, :name
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::CustomFieldSerializer < ApplicationSerializer
|
||||
attributes :id, :klass, :name, :type, :serializers
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::LogSerializer < ApplicationSerializer
|
||||
attributes :message, :date
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
# frozen_string_literal: true
|
||||
class ::CustomWizard::RealtimeValidation::SimilarTopicsSerializer < ::SimilarTopicSerializer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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, {})
|
||||
|
|
|
@ -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("<p>Text inputs!</p>")
|
||||
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("<p>Text</p>")
|
||||
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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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("<p>Text</p>")
|
||||
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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
Laden …
In neuem Issue referenzieren