0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-22 01:10:28 +01:00

COMPATIBILITY: update linting

Dieser Commit ist enthalten in:
Angus McLeod 2024-10-16 13:52:03 +02:00
Ursprung a163ba56ae
Commit f042f6b9b8
103 geänderte Dateien mit 2736 neuen und 3210 gelöschten Zeilen

Datei anzeigen

@ -1,5 +1,10 @@
inherit_gem:
rubocop-discourse: default.yml
rubocop-discourse: stree-compat.yml
AllCops:
Exclude:
- 'gems/**/*'
- 'vendor/**/*'
RSpec/ContextWording:
Enabled: false

2
.streerc Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
--print-width=100
--plugins=plugin/trailing_comma,plugin/disable_auto_ternary

Datei anzeigen

@ -1,8 +1,9 @@
# frozen_string_literal: true
source 'https://rubygems.org'
source "https://rubygems.org"
group :development do
gem 'rubocop-discourse'
gem 'racc'
gem "rubocop-discourse"
gem "syntax_tree"
gem "racc"
end

Datei anzeigen

@ -28,6 +28,7 @@ GEM
parser (3.3.5.0)
ast (~> 2.4.1)
racc
prettier_print (1.2.1)
racc (1.8.1)
rack (3.1.7)
rainbow (3.1.1)
@ -68,6 +69,8 @@ GEM
rubocop-rspec (~> 3, >= 3.0.1)
ruby-progressbar (1.13.0)
securerandom (0.3.1)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
@ -79,6 +82,7 @@ PLATFORMS
DEPENDENCIES
racc
rubocop-discourse
syntax_tree
BUNDLED WITH
2.5.18

Datei anzeigen

@ -3,21 +3,28 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
skip_before_action :check_xhr, only: [:redirect]
def list
serializer = ActiveModel::ArraySerializer.new(CustomWizard::Api.list,
each_serializer: CustomWizard::BasicApiSerializer
serializer =
ActiveModel::ArraySerializer.new(
CustomWizard::Api.list,
each_serializer: CustomWizard::BasicApiSerializer,
)
render json: MultiJson.dump(serializer)
end
def find
render_serialized(CustomWizard::Api.get(api_params[:name]), CustomWizard::ApiSerializer, root: false)
render_serialized(
CustomWizard::Api.get(api_params[:name]),
CustomWizard::ApiSerializer,
root: false,
)
end
def save
current = CustomWizard::Api.get(api_params[:name])
if api_params[:new] && current
raise Discourse::InvalidParameters, "An API with that name already exists: '#{current.title || current.name}'"
raise Discourse::InvalidParameters,
"An API with that name already exists: '#{current.title || current.name}'"
end
unless subscription.includes?(:api, :all)
@ -28,27 +35,27 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
CustomWizard::Api.set(api_params[:name], title: api_params[:title])
if auth_data.present?
auth_data['auth_params'] = auth_data['auth_params'] || []
auth_data["auth_params"] = auth_data["auth_params"] || []
CustomWizard::Api::Authorization.set(api_params[:name], auth_data)
end
if api_params[:endpoints].is_a? String
begin
endpoints = JSON.parse(api_params[:endpoints])
endpoints.each do |endpoint|
CustomWizard::Api::Endpoint.set(api_params[:name], endpoint)
end
endpoints.each { |endpoint| CustomWizard::Api::Endpoint.set(api_params[:name], endpoint) }
rescue => e
puts e
end
end
end
render json: success_json.merge(
api: CustomWizard::ApiSerializer.new(
render json:
success_json.merge(
api:
CustomWizard::ApiSerializer.new(
CustomWizard::Api.get(api_params[:name]),
root: false
)
root: false,
),
)
end
@ -67,13 +74,15 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
result = CustomWizard::Api::Authorization.get_token(api_params[:name])
if result.instance_variable_defined?(:@error)
render json: failed_json.merge(message: result['error_description'] || result['error'])
render json: failed_json.merge(message: result["error_description"] || result["error"])
else
render json: success_json.merge(
api: CustomWizard::ApiSerializer.new(
render json:
success_json.merge(
api:
CustomWizard::ApiSerializer.new(
CustomWizard::Api.get(api_params[:name]),
root: false
)
root: false,
),
)
end
end
@ -90,7 +99,7 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
CustomWizard::Api::Authorization.set(params[:name], code: params[:code])
CustomWizard::Api::Authorization.get_token(params[:name])
redirect_to path('/admin/wizards/apis/' + params[:name])
redirect_to path("/admin/wizards/apis/" + params[:name])
end
private
@ -98,7 +107,8 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
def api_params
params.require(:name)
data = params.permit(
data =
params.permit(
:name,
:title,
:auth_type,
@ -110,7 +120,7 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
:password,
:auth_params,
:endpoints,
:new
:new,
).to_h
data[:name] = data[:name].underscore
@ -119,7 +129,8 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
end
def auth_data
auth_data = api_params.slice(
auth_data =
api_params.slice(
:auth_type,
:auth_url,
:token_url,
@ -127,10 +138,12 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
:client_secret,
:username,
:password,
:auth_params
:auth_params,
)
auth_data[:auth_params] = JSON.parse(auth_data[:auth_params]) if auth_data[:auth_params].present?
auth_data[:auth_params] = JSON.parse(auth_data[:auth_params]) if auth_data[
:auth_params
].present?
@auth_data ||= auth_data
end

Datei anzeigen

@ -1,9 +1,7 @@
# frozen_string_literal: true
class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
def index
render_json_dump(
custom_fields: custom_field_list
)
render_json_dump(custom_fields: custom_field_list)
end
def update
@ -12,23 +10,24 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
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
CustomWizard::CustomField::ATTRS.each { |attr| field_data[attr] = saved_field.send(attr) }
field_id = saved_field.id
end
CustomWizard::CustomField::ATTRS.each do |attr|
field_data[attr] = field_params[attr]
end
CustomWizard::CustomField::ATTRS.each { |attr| field_data[attr] = field_params[attr] }
field = CustomWizard::CustomField.new(field_id, field_data)
PluginStoreRow.transaction do
unless field.save
field_errors = field.errors.any? ?
field.errors.full_messages.join("\n\n") :
field_errors =
(
if field.errors.any?
field.errors.full_messages.join("\n\n")
else
I18n.t("wizard.custom_field.error.save_default", name: field.name)
end
)
errors << field_errors
raise ActiveRecord::Rollback.new
end
@ -54,13 +53,6 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
private
def field_params
params.required(:custom_field)
.permit(
:id,
:name,
:klass,
:type,
serializers: []
)
params.required(:custom_field).permit(:id, :name, :klass, :type, serializers: [])
end
end

Datei anzeigen

@ -3,39 +3,42 @@ class CustomWizard::AdminLogsController < CustomWizard::AdminController
before_action :find_wizard, except: [:index]
def index
render json: ActiveModel::ArraySerializer.new(
render json:
ActiveModel::ArraySerializer.new(
CustomWizard::Wizard.list(current_user),
each_serializer: CustomWizard::BasicWizardSerializer
each_serializer: CustomWizard::BasicWizardSerializer,
)
end
def show
render_json_dump(
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
logs: ActiveModel::ArraySerializer.new(
logs:
ActiveModel::ArraySerializer.new(
log_list.logs,
each_serializer: CustomWizard::LogSerializer
each_serializer: CustomWizard::LogSerializer,
),
total: log_list.total
total: log_list.total,
)
end
protected
def log_list
@log_list ||= begin
@log_list ||=
begin
list = CustomWizard::Log.list(params[:page].to_i, params[:limit].to_i, params[:wizard_id])
if list.logs.any? && (usernames = list.logs.map(&:username)).present?
user_map = User.where(username: usernames)
user_map =
User
.where(username: usernames)
.reduce({}) do |result, user|
result[user.username] = user
result
end
list.logs.each do |log_item|
log_item.user = user_map[log_item.username]
end
list.logs.each { |log_item| log_item.user = user_map[log_item.username] }
end
list

Datei anzeigen

@ -12,38 +12,32 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController
end
end
if templates.empty?
return render_error(I18n.t('wizard.export.error.invalid_wizards'))
end
return render_error(I18n.t("wizard.export.error.invalid_wizards")) if templates.empty?
basename = SiteSetting.title.parameterize || 'discourse'
basename = SiteSetting.title.parameterize || "discourse"
time = Time.now.to_i
filename = "#{basename}-wizards-#{time}.json"
send_data templates.to_json,
type: "application/json",
disposition: 'attachment',
disposition: "attachment",
filename: filename
end
def import
file = File.read(params['file'].tempfile)
file = File.read(params["file"].tempfile)
if file.nil?
return render_error(I18n.t('wizard.export.error.no_file'))
end
return render_error(I18n.t("wizard.export.error.no_file")) if file.nil?
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
return render_error(I18n.t("wizard.import.error.file_large")) if max_file_size < file_size
begin
template_json = JSON.parse(file)
rescue JSON::ParserError
return render_error(I18n.t('wizard.import.error.invalid_json'))
return render_error(I18n.t("wizard.import.error.invalid_json"))
end
imported = []
@ -55,22 +49,13 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController
template.save(skip_jobs: true, create: true)
if template.errors.any?
failures.push(
id: template.data['id'],
messages: template.errors.full_messages.join(', ')
)
failures.push(id: template.data["id"], messages: template.errors.full_messages.join(", "))
else
imported.push(
id: template.data['id'],
name: template.data['name']
)
imported.push(id: template.data["id"], name: template.data["name"])
end
end
render json: success_json.merge(
imported: imported,
failures: failures
)
render json: success_json.merge(imported: imported, failures: failures)
end
def destroy
@ -81,44 +66,34 @@ class CustomWizard::AdminManagerController < CustomWizard::AdminController
template = CustomWizard::Template.find(wizard_id)
if template && CustomWizard::Template.remove(wizard_id)
destroyed.push(
id: wizard_id,
name: template['name']
)
destroyed.push(id: wizard_id, name: template["name"])
else
failures.push(
id: wizard_id,
messages: I18n.t("wizard.destroy.error.#{template ? 'default' : 'no_template'}")
messages: I18n.t("wizard.destroy.error.#{template ? "default" : "no_template"}"),
)
end
end
render json: success_json.merge(
destroyed: destroyed,
failures: failures
)
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
return render_error(I18n.t("wizard.export.error.select_one")) if params["wizard_ids"].blank?
wizard_ids = []
params['wizard_ids'].each do |wizard_id|
params["wizard_ids"].each do |wizard_id|
begin
wizard_ids.push(wizard_id.underscore)
rescue
rescue StandardError
#
end
end
if wizard_ids.empty?
return render_error(I18n.t('wizard.export.error.invalid_wizards'))
end
return render_error(I18n.t("wizard.export.error.invalid_wizards")) if wizard_ids.empty?
@wizard_ids = wizard_ids
end

Datei anzeigen

@ -4,27 +4,30 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
before_action :find_wizard, except: [:index]
def index
render json: ActiveModel::ArraySerializer.new(
render json:
ActiveModel::ArraySerializer.new(
CustomWizard::Wizard.list(current_user),
each_serializer: CustomWizard::BasicWizardSerializer
each_serializer: CustomWizard::BasicWizardSerializer,
)
end
def show
render_json_dump(
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
submissions: ActiveModel::ArraySerializer.new(
submissions:
ActiveModel::ArraySerializer.new(
submission_list.submissions,
each_serializer: CustomWizard::SubmissionSerializer
each_serializer: CustomWizard::SubmissionSerializer,
),
total: submission_list.total
total: submission_list.total,
)
end
def download
content = ActiveModel::ArraySerializer.new(
content =
ActiveModel::ArraySerializer.new(
CustomWizard::Submission.list(@wizard).submissions,
each_serializer: CustomWizard::SubmissionSerializer
each_serializer: CustomWizard::SubmissionSerializer,
)
send_data content.to_json,

Datei anzeigen

@ -1,16 +1,17 @@
# frozen_string_literal: true
class CustomWizard::AdminWizardController < CustomWizard::AdminController
before_action :find_wizard, only: [:show, :remove]
before_action :find_wizard, only: %i[show remove]
def index
render_json_dump(
wizard_list: ActiveModel::ArraySerializer.new(
wizard_list:
ActiveModel::ArraySerializer.new(
CustomWizard::Wizard.list(current_user),
each_serializer: CustomWizard::BasicWizardSerializer
each_serializer: CustomWizard::BasicWizardSerializer,
),
field_types: CustomWizard::Field.types,
realtime_validations: CustomWizard::RealtimeValidation.types,
custom_fields: custom_field_list
custom_fields: custom_field_list,
)
end
@ -37,7 +38,10 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
wizard_id = template.save(create: params[:create])
if template.errors.any?
render json: failed_json.merge(backend_validation_error: template.errors.full_messages.join("\n\n"))
render json:
failed_json.merge(
backend_validation_error: template.errors.full_messages.join("\n\n"),
)
else
render json: success_json.merge(wizard_id: wizard_id)
end
@ -52,16 +56,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
:output,
:output_type,
:output_connector,
pairs: [
:index,
:key,
:key_type,
:value,
:value_type,
:connector,
value: [],
key: [],
],
pairs: [:index, :key, :key_type, :value, :value_type, :connector, value: [], key: []],
output: [],
]
end
@ -120,9 +115,10 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
content: mapped_params,
condition: mapped_params,
index: mapped_params,
validations: {},
validations: {
},
tag_groups: [],
]
],
],
actions: [
:id,
@ -169,8 +165,8 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
visibility_level: mapped_params,
members_visibility_level: mapped_params,
add_event: mapped_params,
add_location: mapped_params
]
add_location: mapped_params,
],
)
end
end

Datei anzeigen

@ -8,9 +8,7 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
update[:fields] = {}
if params[:fields]
field_ids = @builder.wizard.field_ids
params[:fields].each do |k, v|
update[:fields][k] = v if field_ids.include? k
end
params[:fields].each { |k, v| update[:fields][k] = v if field_ids.include? k }
end
@builder.build
@ -34,16 +32,15 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
if current_step.final?
builder.template.actions.each do |action_template|
if action_template['run_after'] === 'wizard_completion'
action_result = CustomWizard::Action.new(
if action_template["run_after"] === "wizard_completion"
action_result =
CustomWizard::Action.new(
action: action_template,
wizard: @wizard,
submission: current_submission
submission: current_submission,
).perform
if action_result.success?
current_submission = action_result.submission
end
current_submission = action_result.submission if action_result.success?
end
end
@ -68,14 +65,14 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
result[:wizard] = ::CustomWizard::WizardSerializer.new(
@wizard,
scope: Guardian.new(current_user),
root: false
root: false,
).as_json
render json: result
else
errors = []
updater.errors.messages.each do |field, msg|
errors << { field: field, description: msg.join(',') }
errors << { field: field, description: msg.join(",") }
end
render json: { errors: errors }, status: 422
end
@ -87,15 +84,14 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?
@step_template = @builder.template.steps.select do |s|
s['id'] == update_params[:step_id]
end.first
@step_template = @builder.template.steps.select { |s| s["id"] == update_params[:step_id] }.first
raise Discourse::InvalidParameters.new(:step_id) if !@step_template
raise Discourse::InvalidAccess.new if !@builder.check_condition(@step_template)
end
def update_params
@update_params || begin
@update_params ||
begin
params.require(:step_id)
params.require(:wizard_id)
params.permit(:wizard_id, :step_id).transform_values { |v| v.underscore }
@ -106,7 +102,7 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
return @result[:redirect_on_next] if @result[:redirect_on_next].present?
submission = @wizard.current_submission
return nil unless submission.present?
return nil if submission.blank?
## route_to set by actions, redirect_on_complete set by actions, redirect_to set at wizard entry
submission.route_to || submission.redirect_on_complete || submission.redirect_to
end

Datei anzeigen

@ -2,9 +2,10 @@
class CustomWizard::WizardController < ::CustomWizard::WizardClientController
def show
if wizard.present?
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json,
status: 200
else
render json: { error: I18n.t('wizard.none') }
render json: { error: I18n.t("wizard.none") }
end
end
@ -12,10 +13,10 @@ class CustomWizard::WizardController < ::CustomWizard::WizardClientController
params.require(:wizard_id)
if wizard.required && !wizard.completed? && wizard.permitted?
return render json: { error: I18n.t('wizard.no_skip') }
return render json: { error: I18n.t("wizard.no_skip") }
end
result = { success: 'OK' }
result = { success: "OK" }
if current_user && wizard.can_access?
if redirect_to = wizard.current_submission&.redirect_to
@ -31,8 +32,9 @@ class CustomWizard::WizardController < ::CustomWizard::WizardClientController
protected
def wizard
@wizard ||= begin
return nil unless @builder.present?
@wizard ||=
begin
return nil if @builder.blank?
@builder.build({ reset: params[:reset] }, params)
end
end

Datei anzeigen

@ -6,9 +6,7 @@ class CustomWizard::WizardClientController < ::ApplicationController
private
def ensure_plugin_enabled
unless SiteSetting.custom_wizard_enabled
redirect_to path("/")
end
redirect_to path("/") unless SiteSetting.custom_wizard_enabled
end
def guest_id

Datei anzeigen

@ -9,9 +9,7 @@ module Jobs
user_ids = []
User.human_users.each do |user|
if CustomWizard::Wizard.set_user_redirect(wizard.id, user)
user_ids.push(user.id)
end
user_ids.push(user.id) if CustomWizard::Wizard.set_user_redirect(wizard.id, user)
end
CustomWizard::Template.clear_cache_keys

Datei anzeigen

@ -1,5 +1,4 @@
# frozen_string_literal: true
class CustomWizard::Api::BasicEndpointSerializer < ::ApplicationSerializer
attributes :id,
:name
attributes :id, :name
end

Datei anzeigen

@ -1,13 +1,8 @@
# frozen_string_literal: true
class CustomWizard::Api::EndpointSerializer < ::ApplicationSerializer
attributes :id,
:name,
:method,
:url,
:content_type,
:success_codes
attributes :id, :name, :method, :url, :content_type, :success_codes
def method
object.send('method')
object.send("method")
end
end

Datei anzeigen

@ -1,17 +1,10 @@
# frozen_string_literal: true
class CustomWizard::ApiSerializer < ::ApplicationSerializer
attributes :name,
:title,
:authorization,
:endpoints,
:log
attributes :name, :title, :authorization, :endpoints, :log
def authorization
if authorization = CustomWizard::Api::Authorization.get(object.name)
CustomWizard::Api::AuthorizationSerializer.new(
authorization,
root: false
)
CustomWizard::Api::AuthorizationSerializer.new(authorization, root: false)
end
end
@ -19,17 +12,14 @@ class CustomWizard::ApiSerializer < ::ApplicationSerializer
if endpoints = CustomWizard::Api::Endpoint.list(object.name)
ActiveModel::ArraySerializer.new(
endpoints,
each_serializer: CustomWizard::Api::EndpointSerializer
each_serializer: CustomWizard::Api::EndpointSerializer,
)
end
end
def log
if log = CustomWizard::Api::LogEntry.list(object.name)
ActiveModel::ArraySerializer.new(
log,
each_serializer: CustomWizard::Api::LogSerializer
)
ActiveModel::ArraySerializer.new(log, each_serializer: CustomWizard::Api::LogSerializer)
end
end
end

Datei anzeigen

@ -1,14 +1,12 @@
# frozen_string_literal: true
class CustomWizard::BasicApiSerializer < ::ApplicationSerializer
attributes :name,
:title,
:endpoints
attributes :name, :title, :endpoints
def endpoints
if endpoints = CustomWizard::Api::Endpoint.list(object.name)
ActiveModel::ArraySerializer.new(
endpoints,
each_serializer: CustomWizard::Api::BasicEndpointSerializer
each_serializer: CustomWizard::Api::BasicEndpointSerializer,
)
end
end

Datei anzeigen

@ -1,10 +1,7 @@
# frozen_string_literal: true
class CustomWizard::LogSerializer < ApplicationSerializer
attributes :date,
:action,
:username,
:message
attributes :date, :action, :username, :message
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
end

Datei anzeigen

@ -1,9 +1,6 @@
# frozen_string_literal: true
class CustomWizard::SubmissionSerializer < ApplicationSerializer
attributes :id,
:fields,
:submitted_at,
:user
attributes :id, :fields, :submitted_at, :user
def include_user?
object.wizard.user.present?
@ -14,17 +11,14 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer
end
def fields
@fields ||= begin
@fields ||=
begin
result = {}
object.wizard.template['steps'].each do |step|
step['fields'].each do |field|
if value = object.fields[field['id']]
result[field['id']] = {
value: value,
type: field['type'],
label: field['label']
}
object.wizard.template["steps"].each do |step|
step["fields"].each do |field|
if value = object.fields[field["id"]]
result[field["id"]] = { value: value, type: field["type"], label: field["label"] }
end
end
end

Datei anzeigen

@ -1,7 +1,6 @@
# frozen_string_literal: true
class CustomWizard::FieldSerializer < ::ApplicationSerializer
attributes :id,
:index,
:type,
@ -109,7 +108,9 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
object.validations&.each do |type, props|
next unless props["status"]
validations[props["position"]] ||= {}
validations[props["position"]][type] = props.merge CustomWizard::RealtimeValidation.types[type.to_sym]
validations[props["position"]][type] = props.merge CustomWizard::RealtimeValidation.types[
type.to_sym
]
end
validations

Datei anzeigen

@ -1,7 +1,6 @@
# frozen_string_literal: true
class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
attributes :start,
:background,
:submission_last_updated_at,

Datei anzeigen

@ -1,7 +1,6 @@
# frozen_string_literal: true
class CustomWizard::StepSerializer < ::ApplicationSerializer
attributes :id,
:index,
:next,

Datei anzeigen

@ -1,49 +1,49 @@
# frozen_string_literal: true
CustomWizard::Engine.routes.draw do
get ':wizard_id' => 'wizard#show'
put ':wizard_id/skip' => 'wizard#skip'
get ':wizard_id/steps' => 'wizard#show'
get ':wizard_id/steps/:step_id' => 'wizard#show'
put ':wizard_id/steps/:step_id' => 'steps#update'
get ":wizard_id" => "wizard#show"
put ":wizard_id/skip" => "wizard#skip"
get ":wizard_id/steps" => "wizard#show"
get ":wizard_id/steps/:step_id" => "wizard#show"
put ":wizard_id/steps/:step_id" => "steps#update"
end
Discourse::Application.routes.append do
mount ::CustomWizard::Engine, at: 'w'
post 'wizard/authorization/callback' => "custom_wizard/authorization#callback"
get 'realtime-validations' => 'custom_wizard/realtime_validations#validate'
mount ::CustomWizard::Engine, at: "w"
post "wizard/authorization/callback" => "custom_wizard/authorization#callback"
get "realtime-validations" => "custom_wizard/realtime_validations#validate"
scope module: 'custom_wizard', constraints: AdminConstraint.new do
get 'admin/wizards' => 'admin#index'
get 'admin/wizards/subscription' => 'subscription#index'
scope module: "custom_wizard", constraints: AdminConstraint.new do
get "admin/wizards" => "admin#index"
get "admin/wizards/subscription" => "subscription#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/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/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/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'
delete 'admin/wizards/api/:name' => 'admin_api#remove'
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/api" => "admin_api#list"
get "admin/wizards/api/:name" => "admin_api#find"
put "admin/wizards/api/:name" => "admin_api#save"
delete "admin/wizards/api/:name" => "admin_api#remove"
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/logs/:wizard_id' => 'admin_logs#show'
get "admin/wizards/logs" => "admin_logs#index"
get "admin/wizards/logs/:wizard_id" => "admin_logs#show"
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'
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

Datei anzeigen

@ -1,10 +1,13 @@
# frozen_string_literal: true
class UpdateWatchCategoriesAction < ActiveRecord::Migration[6.0]
def change
watch_category_wizards = PluginStoreRow.where("
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|
@ -14,10 +17,8 @@ class UpdateWatchCategoriesAction < ActiveRecord::Migration[6.0]
next
end
wizard_json['actions'].each do |a|
if a['type'] === "watch_categories" && a['wizard_user'] == nil
a['wizard_user'] = true
end
wizard_json["actions"].each do |a|
a["wizard_user"] = true if a["type"] === "watch_categories" && a["wizard_user"] == nil
end
row.value = wizard_json.to_json

Datei anzeigen

@ -5,7 +5,7 @@ class SplitCustomWizardLogFields < ActiveRecord::Migration[6.1]
action: "action",
user: "username",
date: "date",
message: "message"
message: "message",
}
def change
@ -23,22 +23,21 @@ class SplitCustomWizardLogFields < ActiveRecord::Migration[6.1]
next
end
if log_json.key?('message') && log_json['message'].is_a?(String)
if log_json.key?("message") && log_json["message"].is_a?(String)
attr_strs = []
# assumes no whitespace in the values
attr_strs << log_json['message'].slice!(/(wizard: \S*; )/, 1)
attr_strs << log_json['message'].slice!(/(action: \S*; )/, 1)
attr_strs << log_json['message'].slice!(/(user: \S*; )/, 1)
attr_strs << log_json["message"].slice!(/(wizard: \S*; )/, 1)
attr_strs << log_json["message"].slice!(/(action: \S*; )/, 1)
attr_strs << log_json["message"].slice!(/(user: \S*; )/, 1)
attr_strs.each do |attr_str|
if attr_str.is_a? String
attr_str.gsub!(/[;]/, "")
key, value = attr_str.split(': ')
key, value = attr_str.split(": ")
value.strip! if value
key = KEY_MAP[key.to_sym] ? KEY_MAP[key.to_sym] : key
log_json[key] = value ? value : ''
log_json[key] = value ? value : ""
end
end
@ -61,22 +60,25 @@ class SplitCustomWizardLogFields < ActiveRecord::Migration[6.1]
end
# concatenate wizard/action/user to start of message
prefixes = log_json.extract!('wizard_id', 'action', 'username')
prefixes = log_json.extract!("wizard_id", "action", "username")
message_prefix = ""
if prefixes.present?
message_prefix = prefixes.map do |k, v|
message_prefix =
prefixes
.map do |k, v|
key = KEY_MAP.key(k) ? KEY_MAP.key(k) : k
"#{key.to_s}: #{v};"
end.join(' ')
"#{key}: #{v};"
end
.join(" ")
end
if log_json.key?('message')
message = log_json['message']
if log_json.key?("message")
message = log_json["message"]
message = "#{message_prefix} #{message}" if message_prefix.present?
log_json['message'] = message
log_json["message"] = message
else
log_json['message'] = message_prefix
log_json["message"] = message_prefix
end
row.value = log_json.to_json

Datei anzeigen

@ -1,19 +1,10 @@
# frozen_string_literal: true
class CustomWizard::Action
attr_accessor :submission,
:action,
:user,
:guardian,
:result
attr_accessor :submission, :action, :user, :guardian, :result
REQUIRES_USER = %w[
update_profile
open_composer
watch_categories
add_to_group
]
REQUIRES_USER = %w[update_profile open_composer watch_categories add_to_group]
WIZARD_USER = 'wizard-user'
WIZARD_USER = "wizard-user"
def initialize(opts)
@wizard = opts[:wizard]
@ -26,23 +17,17 @@ class CustomWizard::Action
end
def perform
if REQUIRES_USER.include?(action['id']) && !@user
log_error("action requires user", "id: #{action['id']};")
if REQUIRES_USER.include?(action["id"]) && !@user
log_error("action requires user", "id: #{action["id"]};")
@result.success = false
return @result
end
ActiveRecord::Base.transaction do
self.send(action['type'].to_sym)
end
ActiveRecord::Base.transaction { self.send(action["type"].to_sym) }
if creates_post? && @result.success?
@result.handler.enqueue_jobs
end
@result.handler.enqueue_jobs if creates_post? && @result.success?
if @result.success? && @result.output.present?
@submission.fields[action['id']] = @result.output
end
@submission.fields[action["id"]] = @result.output if @result.success? && @result.output.present?
save_log
@ -76,7 +61,7 @@ class CustomWizard::Action
if creator.errors.present?
messages = creator.errors.full_messages.join(" ")
log_error("failed to create", messages)
elsif action['skip_redirect'].blank?
elsif action["skip_redirect"].blank?
@submission.redirect_on_complete = post.topic.url
end
@ -91,12 +76,9 @@ class CustomWizard::Action
end
def send_message
if action['required'].present?
required = CustomWizard::Mapper.new(
inputs: action['required'],
data: mapper_data,
user: user
).perform
if action["required"].present?
required =
CustomWizard::Mapper.new(inputs: action["required"], data: mapper_data, user: user).perform
if required.blank?
log_error("required input not present")
@ -106,11 +88,12 @@ class CustomWizard::Action
params = basic_topic_params
targets = CustomWizard::Mapper.new(
inputs: action['recipient'],
targets =
CustomWizard::Mapper.new(
inputs: action["recipient"],
data: mapper_data,
user: user,
multiple: true
multiple: true,
).perform
if targets.blank?
@ -131,12 +114,11 @@ class CustomWizard::Action
end
end
if params[:title].present? &&
params[:raw].present? &&
(params[:target_usernames].present? ||
params[:target_group_names].present? ||
params[:target_emails].present?)
if params[:title].present? && params[:raw].present? &&
(
params[:target_usernames].present? || params[:target_group_names].present? ||
params[:target_emails].present?
)
params[:archetype] = Archetype.private_message
creator = PostCreator.new(topic_poster, params)
@ -145,7 +127,7 @@ class CustomWizard::Action
if creator.errors.present?
messages = creator.errors.full_messages.join(" ")
log_error("failed to create message", messages)
elsif user && action['skip_redirect'].blank?
elsif user && action["skip_redirect"].blank?
@submission.redirect_on_complete = post.topic.url
end
@ -157,7 +139,7 @@ class CustomWizard::Action
else
log_error(
"invalid message params",
"title: #{params[:title]}; post: #{params[:raw]}; recipients: #{params[:target_usernames]}"
"title: #{params[:title]}; post: #{params[:raw]}; recipients: #{params[:target_usernames]}",
)
end
end
@ -165,19 +147,14 @@ class CustomWizard::Action
def update_profile
params = {}
if (profile_updates = action['profile_updates'])
if (profile_updates = action["profile_updates"])
profile_updates.first[:pairs].each do |pair|
if allowed_profile_field?(pair['key'])
key = cast_profile_key(pair['key'])
value = cast_profile_value(
mapper.map_field(
pair['value'],
pair['value_type']
),
pair['key']
)
if allowed_profile_field?(pair["key"])
key = cast_profile_key(pair["key"])
value =
cast_profile_value(mapper.map_field(pair["value"], pair["value_type"]), pair["key"])
if user_field?(pair['key'])
if user_field?(pair["key"])
params[:custom_fields] ||= {}
params[:custom_fields][key] = value
else
@ -192,12 +169,10 @@ class CustomWizard::Action
if params.present?
result = UserUpdater.new(Discourse.system_user, user).update(params)
if params[:avatar].present?
result = update_avatar(params[:avatar])
end
result = update_avatar(params[:avatar]) if params[:avatar].present?
if result
log_success("updated profile fields", "fields: #{params.keys.map(&:to_s).join(',')}")
log_success("updated profile fields", "fields: #{params.keys.map(&:to_s).join(",")}")
else
log_error("failed to update profile fields", "result: #{result.inspect}")
end
@ -207,14 +182,10 @@ class CustomWizard::Action
end
def watch_tags
tags = CustomWizard::Mapper.new(
inputs: action['tags'],
data: mapper_data,
user: user
).perform
tags = CustomWizard::Mapper.new(inputs: action["tags"], data: mapper_data, user: user).perform
tags = [*tags]
level = action['notification_level'].to_sym
level = action["notification_level"].to_sym
if level.blank?
log_error("Notifcation Level was not set. Exiting watch tags action")
@ -223,23 +194,17 @@ class CustomWizard::Action
users = []
if action['usernames']
mapped_users = CustomWizard::Mapper.new(
inputs: action['usernames'],
data: mapper_data,
user: user
).perform
if action["usernames"]
mapped_users =
CustomWizard::Mapper.new(inputs: action["usernames"], data: mapper_data, user: user).perform
if mapped_users.present?
mapped_users = mapped_users.split(',')
.map { |username| User.find_by(username: username) }
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
users.push(user) if ActiveRecord::Type::Boolean.new.cast(action["wizard_user"])
users.each do |user|
result = TagUser.batch_set(user, level, tags)
@ -253,46 +218,38 @@ class CustomWizard::Action
end
def watch_categories
watched_categories = CustomWizard::Mapper.new(
inputs: action['categories'],
data: mapper_data,
user: user
).perform
watched_categories =
CustomWizard::Mapper.new(inputs: action["categories"], data: mapper_data, user: user).perform
watched_categories = [*watched_categories].map(&:to_i)
notification_level = action['notification_level']
notification_level = action["notification_level"]
if notification_level.blank?
log_error("Notifcation Level was not set. Exiting wizard action")
return
end
mute_remainder = CustomWizard::Mapper.new(
inputs: action['mute_remainder'],
mute_remainder =
CustomWizard::Mapper.new(
inputs: action["mute_remainder"],
data: mapper_data,
user: user
user: user,
).perform
users = []
if action['usernames']
mapped_users = CustomWizard::Mapper.new(
inputs: action['usernames'],
data: mapper_data,
user: user
).perform
if action["usernames"]
mapped_users =
CustomWizard::Mapper.new(inputs: action["usernames"], data: mapper_data, user: user).perform
if mapped_users.present?
mapped_users = mapped_users.split(',')
.map { |username| User.find_by(username: username) }
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
users.push(user) if ActiveRecord::Type::Boolean.new.cast(action["wizard_user"])
category_ids = Category.all.pluck(:id)
set_level = CategoryUser.notification_levels[notification_level.to_sym]
@ -308,37 +265,35 @@ class CustomWizard::Action
new_level = mute_level
end
if new_level
CategoryUser.set_notification_level_for_category(user, new_level, category_id)
end
CategoryUser.set_notification_level_for_category(user, new_level, category_id) if new_level
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
log_success("#{user.username} notifications for all other categories muted") if mute_remainder
end
end
def send_to_api
api_body = nil
if action['api_body'] != ""
if action["api_body"] != ""
begin
api_body_parsed = JSON.parse(action['api_body'])
api_body_parsed = JSON.parse(action["api_body"])
rescue JSON::ParserError
raise Discourse::InvalidParameters, "Invalid API body definition: #{action['api_body']} for #{action['title']}"
raise Discourse::InvalidParameters,
"Invalid API body definition: #{action["api_body"]} for #{action["title"]}"
end
api_body = JSON.parse(mapper.interpolate(JSON.generate(api_body_parsed)))
end
result = CustomWizard::Api::Endpoint.request(user, action['api'], action['api_endpoint'], api_body)
result =
CustomWizard::Api::Endpoint.request(user, action["api"], action["api_endpoint"], api_body)
if error = result['error'] || (result[0] && result[0]['error'])
error = error['message'] || error
if error = result["error"] || (result[0] && result[0]["error"])
error = error["message"] || error
log_error("api request failed", "message: #{error}")
else
log_success("api request succeeded", "result: #{result}")
@ -357,7 +312,7 @@ class CustomWizard::Action
end
if tags = action_tags
url += "&tags=#{tags.join(',')}"
url += "&tags=#{tags.join(",")}"
end
route_to = Discourse.base_uri + url
@ -370,13 +325,14 @@ class CustomWizard::Action
end
def add_to_group
group_map = CustomWizard::Mapper.new(
inputs: action['group'],
group_map =
CustomWizard::Mapper.new(
inputs: action["group"],
data: mapper_data,
user: user,
opts: {
multiple: true
}
multiple: true,
},
).perform
group_map = group_map.flatten.compact
@ -386,7 +342,8 @@ class CustomWizard::Action
return
end
groups = group_map.reduce([]) do |result, g|
groups =
group_map.reduce([]) do |result, g|
begin
result.push(Integer(g))
rescue ArgumentError
@ -407,29 +364,25 @@ class CustomWizard::Action
end
if result
log_success("added to groups", "groups: #{groups.map(&:to_s).join(',')}")
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 if (url_input = action['url']).blank?
return if (url_input = action["url"]).blank?
if url_input.is_a?(String)
url = mapper.interpolate(url_input)
else
url = CustomWizard::Mapper.new(
inputs: url_input,
data: mapper_data,
user: user
).perform
url = CustomWizard::Mapper.new(inputs: url_input, data: mapper_data, user: user).perform
end
if action['code'].present?
@submission.fields[action['code']] = SecureRandom.hex(8)
url += "&#{action['code']}=#{@submission.fields[action['code']]}"
if action["code"].present?
@submission.fields[action["code"]] = SecureRandom.hex(8)
url += "&#{action["code"]}=#{@submission.fields[action["code"]]}"
end
route_to = UrlHelper.encode(url)
@ -465,9 +418,7 @@ class CustomWizard::Action
user_ids.each { |user_id| group.group_users.build(user_id: user_id) }
end
if group.save
log_success("Group created", group.name)
end
log_success("Group created", group.name) if group.save
result.output = group.name
else
@ -504,11 +455,8 @@ class CustomWizard::Action
private
def action_category
output = CustomWizard::Mapper.new(
inputs: action['category'],
data: mapper_data,
user: user
).perform
output =
CustomWizard::Mapper.new(inputs: action["category"], data: mapper_data, user: user).perform
return false if output.blank?
@ -522,32 +470,26 @@ class CustomWizard::Action
end
def action_tags
output = CustomWizard::Mapper.new(
inputs: action['tags'],
data: mapper_data,
user: user,
).perform
output = CustomWizard::Mapper.new(inputs: action["tags"], data: mapper_data, user: user).perform
return false if output.blank?
if output.is_a?(Array)
output.flatten
else output.is_a?(String)
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(
inputs: custom_fields,
data: mapper_data,
user: user
).perform
if (custom_fields = action["custom_fields"]).present?
field_map =
CustomWizard::Mapper.new(inputs: custom_fields, data: mapper_data, user: user).perform
registered_fields = CustomWizard::CustomField.full_list
field_map.each do |field|
keyArr = field[:key].split('.')
keyArr = field[:key].split(".")
value = field[:value]
if keyArr.length > 1
@ -601,28 +543,32 @@ class CustomWizard::Action
skip_validations: true,
topic_opts: {
custom_fields: {
wizard_submission_id: @wizard.current_submission.id
}
}
wizard_submission_id: @wizard.current_submission.id,
},
},
}
params[:title] = CustomWizard::Mapper.new(
inputs: action['title'],
inputs: action["title"],
data: mapper_data,
user: user
user: user,
).perform
params[:raw] = action['post_builder'] ?
params[:raw] = (
if action["post_builder"]
mapper.interpolate(
action['post_template'],
action["post_template"],
user: true,
value: true,
wizard: true,
template: true
) :
@submission.fields[action['post']]
template: true,
)
else
@submission.fields[action["post"]]
end
)
params[:import_mode] = ActiveRecord::Type::Boolean.new.cast(action['suppress_notifications'])
params[:import_mode] = ActiveRecord::Type::Boolean.new.cast(action["suppress_notifications"])
add_custom_fields(params)
end
@ -644,7 +590,7 @@ class CustomWizard::Action
params[field.to_sym] = CustomWizard::Mapper.new(
inputs: action[field],
data: mapper_data,
user: user
user: user,
).perform
end
end
@ -654,12 +600,10 @@ class CustomWizard::Action
end
def topic_poster
@topic_poster ||= begin
poster_id = CustomWizard::Mapper.new(
inputs: action['poster'],
data: mapper_data,
user: user,
).perform
@topic_poster ||=
begin
poster_id =
CustomWizard::Mapper.new(inputs: action["poster"], data: mapper_data, user: user).perform
poster_id = [*poster_id].first if poster_id.present?
if poster_id.blank? || poster_id === WIZARD_USER
@ -673,13 +617,11 @@ class CustomWizard::Action
end
def guest_user
@guest_user ||= begin
return nil unless action['guest_email']
@guest_user ||=
begin
return nil unless action["guest_email"]
email = CustomWizard::Mapper.new(
inputs: action['guest_email'],
data: mapper_data,
).perform
email = CustomWizard::Mapper.new(inputs: action["guest_email"], data: mapper_data).perform
if email&.match(/@/)
if user = User.find_by_email(email)
@ -699,7 +641,7 @@ class CustomWizard::Action
def new_group_params
params = {}
%w(
%w[
name
full_name
title
@ -711,26 +653,18 @@ class CustomWizard::Action
visibility_level
members_visibility_level
grant_trust_level
).each do |attr|
].each do |attr|
input = action[attr]
if attr === "name" && input.blank?
raise ArgumentError.new
end
raise ArgumentError.new if attr === "name" && input.blank?
if attr === "full_name" && input.blank?
input = action["name"]
end
input = action["name"] if attr === "full_name" && input.blank?
if input.present?
value = CustomWizard::Mapper.new(
inputs: input,
data: mapper_data,
user: user
).perform
value = CustomWizard::Mapper.new(inputs: input, data: mapper_data, user: user).perform
if value
value = value.parameterize(separator: '_') if attr === "name"
value = value.parameterize(separator: "_") if attr === "name"
value = value.to_i if attr.include?("_level")
params[attr.to_sym] = value
@ -744,25 +678,13 @@ class CustomWizard::Action
def new_category_params
params = {}
%w(
name
slug
color
text_color
parent_category_id
permissions
).each do |attr|
%w[name slug color text_color parent_category_id permissions].each do |attr|
if action[attr].present?
value = CustomWizard::Mapper.new(
inputs: action[attr],
data: mapper_data,
user: user
).perform
value =
CustomWizard::Mapper.new(inputs: action[attr], data: mapper_data, user: user).perform
if value
if attr === "parent_category_id" && value.is_a?(Array)
value = value[0]
end
value = value[0] if attr === "parent_category_id" && value.is_a?(Array)
if attr === "permissions" && value.is_a?(Array)
permissions = value
@ -776,16 +698,14 @@ class CustomWizard::Action
group = Group.find_by(id: k[0])
k = group.name
else
k = k.parameterize(separator: '_')
k = k.parameterize(separator: "_")
end
value[k] = v
end
end
if attr === 'slug'
value = value.parameterize(separator: '-')
end
value = value.parameterize(separator: "-") if attr === "slug"
params[attr.to_sym] = value
end
@ -796,15 +716,15 @@ class CustomWizard::Action
end
def creates_post?
[:create_topic, :send_message].include?(action['type'].to_sym)
%i[create_topic send_message].include?(action["type"].to_sym)
end
def public_topic_fields
['visible']
["visible"]
end
def profile_url_fields
['profile_background', 'card_background']
%w[profile_background card_background]
end
def cast_profile_key(key)
@ -819,16 +739,16 @@ class CustomWizard::Action
return value if value.nil?
if profile_url_fields.include?(key)
value['url']
elsif key === 'avatar'
value['id']
value["url"]
elsif key === "avatar"
value["id"]
else
value
end
end
def profile_excluded_fields
['username', 'email', 'trust_level'].freeze
%w[username email trust_level].freeze
end
def allowed_profile_field?(field)
@ -837,13 +757,12 @@ class CustomWizard::Action
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 +
['avatar']
profile_url_fields + ["avatar"]
end
def update_avatar(upload_id)
@ -875,11 +794,6 @@ class CustomWizard::Action
def save_log
username = user ? user.username : @wizard.actor_id
CustomWizard::Log.create(
@wizard.id,
action['type'],
username,
@log.join('; ')
)
CustomWizard::Log.create(@wizard.id, action["type"], username, @log.join("; "))
end
end

Datei anzeigen

@ -2,14 +2,11 @@
class CustomWizard::Api
include ActiveModel::SerializerSupport
attr_accessor :name,
:title
attr_accessor :name, :title
def initialize(name, data = {})
@name = name
data.each do |k, v|
self.send "#{k}=", v if self.respond_to?(k)
end
data.each { |k, v| self.send "#{k}=", v if self.respond_to?(k) }
end
def self.set(name, data)
@ -27,9 +24,10 @@ class CustomWizard::Api
end
def self.list
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_%' AND key = 'metadata'")
PluginStoreRow
.where("plugin_name LIKE 'custom_wizard_api_%' AND key = 'metadata'")
.map do |record|
self.new(record['plugin_name'].sub("custom_wizard_api_", ""), ::JSON.parse(record['value']))
self.new(record["plugin_name"].sub("custom_wizard_api_", ""), ::JSON.parse(record["value"]))
end
end
end

Datei anzeigen

@ -1,5 +1,5 @@
# frozen_string_literal: true
require 'excon'
require "excon"
class CustomWizard::Api::Authorization
include ActiveModel::SerializerSupport
@ -23,9 +23,7 @@ class CustomWizard::Api::Authorization
def initialize(api_name, data = {})
@api_name = api_name
data.each do |k, v|
self.send "#{k}=", v if self.respond_to?(k)
end
data.each { |k, v| self.send "#{k}=", v if self.respond_to?(k) }
end
def authorized
@ -33,16 +31,13 @@ class CustomWizard::Api::Authorization
end
def self.set(api_name, new_data = {})
api_name = api_name.underscore
data = self.get(api_name, data_only: true) || {}
new_data.each do |k, v|
data[k.to_sym] = v
end
new_data.each { |k, v| data[k.to_sym] = v }
PluginStore.set("custom_wizard_api_#{api_name}", 'authorization', data)
PluginStore.set("custom_wizard_api_#{api_name}", "authorization", data)
self.get(api_name)
end
@ -50,7 +45,7 @@ class CustomWizard::Api::Authorization
def self.get(api_name, opts = {})
api_name = api_name.underscore
if data = PluginStore.get("custom_wizard_api_#{api_name}", 'authorization')
if data = PluginStore.get("custom_wizard_api_#{api_name}", "authorization")
if opts[:data_only]
data
else
@ -67,14 +62,14 @@ class CustomWizard::Api::Authorization
def self.authorization_string(name)
auth = CustomWizard::Api::Authorization.get(name)
raise Discourse::InvalidParameters.new(:name) unless auth.present?
raise Discourse::InvalidParameters.new(:name) if auth.blank?
if auth.auth_type === "basic"
raise Discourse::InvalidParameters.new(:username) unless auth.username.present?
raise Discourse::InvalidParameters.new(:password) unless auth.password.present?
raise Discourse::InvalidParameters.new(:username) if auth.username.blank?
raise Discourse::InvalidParameters.new(:password) if auth.password.blank?
"Basic #{Base64.strict_encode64((auth.username + ":" + auth.password).chomp)}"
elsif ['oauth_3', 'oauth_2'].include?(auth.auth_type)
raise Discourse::InvalidParameters.new(auth.access_token) unless auth.access_token.present?
elsif %w[oauth_3 oauth_2].include?(auth.auth_type)
raise Discourse::InvalidParameters.new(auth.access_token) if auth.access_token.blank?
"Bearer #{auth.access_token}"
else
nil
@ -87,38 +82,51 @@ class CustomWizard::Api::Authorization
body = {}
if opts[:refresh] && type === 'oauth_3'
body['grant_type'] = 'refresh_token'
elsif type === 'oauth_2'
body['grant_type'] = 'client_credentials'
elsif type === 'oauth_3'
body['grant_type'] = 'authorization_code'
if opts[:refresh] && type === "oauth_3"
body["grant_type"] = "refresh_token"
elsif type === "oauth_2"
body["grant_type"] = "client_credentials"
elsif type === "oauth_3"
body["grant_type"] = "authorization_code"
end
unless opts[:refresh]
body['client_id'] = authorization.client_id
body['client_secret'] = authorization.client_secret
body["client_id"] = authorization.client_id
body["client_secret"] = authorization.client_secret
end
if type === 'oauth_3'
body['code'] = authorization.code
body['redirect_uri'] = Discourse.base_url + "/admin/wizards/apis/#{name}/redirect"
if type === "oauth_3"
body["code"] = authorization.code
body["redirect_uri"] = Discourse.base_url + "/admin/wizards/apis/#{name}/redirect"
end
connection = Excon.new(
connection =
Excon.new(
authorization.token_url,
headers: {
"Content-Type" => "application/x-www-form-urlencoded"
"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
@ -128,25 +136,21 @@ class CustomWizard::Api::Authorization
def self.handle_token_result(name, result)
result_data = JSON.parse(result.body)
if result_data['error']
return result_data
end
return result_data if result_data["error"]
data = {}
data['access_token'] = result_data['access_token']
data['refresh_token'] = result_data['refresh_token'] if result_data['refresh_token']
data['token_type'] = result_data['token_type'] if result_data['token_type']
data["access_token"] = result_data["access_token"]
data["refresh_token"] = result_data["refresh_token"] if result_data["refresh_token"]
data["token_type"] = result_data["token_type"] if result_data["token_type"]
if result_data['expires_in']
data['token_expires_at'] = Time.now + result_data['expires_in'].seconds
data['token_refresh_at'] = data['token_expires_at'].to_time - 10.minutes
if result_data["expires_in"]
data["token_expires_at"] = Time.now + result_data["expires_in"].seconds
data["token_refresh_at"] = data["token_expires_at"].to_time - 10.minutes
opts = {
name: name
}
opts = { name: name }
Jobs.enqueue_at(data['token_refresh_at'], :refresh_api_access_token, opts)
Jobs.enqueue_at(data["token_refresh_at"], :refresh_api_access_token, opts)
end
CustomWizard::Api::Authorization.set(name, data)

Datei anzeigen

@ -2,34 +2,24 @@
class CustomWizard::Api::Endpoint
include ActiveModel::SerializerSupport
attr_accessor :id,
:name,
:api_name,
:method,
:url,
:content_type,
:success_codes
attr_accessor :id, :name, :api_name, :method, :url, :content_type, :success_codes
def initialize(api_name, data = {})
@api_name = api_name
data.each do |k, v|
self.send "#{k}=", v if self.respond_to?(k)
end
data.each { |k, v| self.send "#{k}=", v if self.respond_to?(k) }
end
def self.set(api_name, new_data)
if new_data['id']
data = self.get(api_name, new_data['id'], data_only: true)
endpoint_id = new_data['id']
if new_data["id"]
data = self.get(api_name, new_data["id"], data_only: true)
endpoint_id = new_data["id"]
else
data = {}
endpoint_id = SecureRandom.hex(3)
end
new_data.each do |k, v|
data[k.to_sym] = v
end
new_data.each { |k, v| data[k.to_sym] = v }
PluginStore.set("custom_wizard_api_#{api_name}", "endpoint_#{endpoint_id}", data)
@ -52,15 +42,18 @@ class CustomWizard::Api::Endpoint
end
def self.remove(api_name)
PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'").destroy_all
PluginStoreRow.where(
"plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'",
).destroy_all
end
def self.list(api_name)
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'")
PluginStoreRow
.where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'")
.map do |record|
api_name = record['plugin_name'].sub("custom_wizard_api_", "")
data = ::JSON.parse(record['value'])
data[:id] = record['key'].split('_').last
api_name = record["plugin_name"].sub("custom_wizard_api_", "")
data = ::JSON.parse(record["value"])
data[:id] = record["key"].split("_").last
self.new(api_name, data)
end
end
@ -97,12 +90,12 @@ class CustomWizard::Api::Endpoint
result = response.body
end
CustomWizard::Api::LogEntry.set(api_name, log_params(user, 'SUCCESS', endpoint.url))
CustomWizard::Api::LogEntry.set(api_name, log_params(user, "SUCCESS", endpoint.url))
result
else
message = "API request failed"
CustomWizard::Api::LogEntry.set(api_name, log_params(user, 'FAIL', endpoint.url, message))
CustomWizard::Api::LogEntry.set(api_name, log_params(user, "FAIL", endpoint.url, message))
{ error: message }
end
end

Datei anzeigen

@ -16,23 +16,19 @@ class CustomWizard::Api::LogEntry
def initialize(api_name, data = {})
@api_name = api_name
data.each do |k, v|
self.send "#{k}=", v if self.respond_to?(k)
end
data.each { |k, v| self.send "#{k}=", v if self.respond_to?(k) }
end
def self.set(api_name, new_data)
if new_data['log_id']
data = self.get(api_name, new_data['log_id'], data_only: true)
log_id = new_data['log_id']
if new_data["log_id"]
data = self.get(api_name, new_data["log_id"], data_only: true)
log_id = new_data["log_id"]
else
data = {}
log_id = SecureRandom.hex(8)
end
new_data.each do |k, v|
data[k.to_sym] = v
end
new_data.each { |k, v| data[k.to_sym] = v }
PluginStore.set("custom_wizard_api_#{api_name}", "log_#{log_id}", data)
@ -55,16 +51,19 @@ class CustomWizard::Api::LogEntry
end
def self.remove(api_name)
PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'").destroy_all
PluginStoreRow.where(
"plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'",
).destroy_all
end
def self.list(api_name)
PluginStoreRow.where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'")
PluginStoreRow
.where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'")
.map do |record|
api_name = record['plugin_name'].sub("custom_wizard_api_", "")
data = ::JSON.parse(record['value'])
data[:log_id] = record['key'].split('_').last
this_user = User.find_by(id: data['user_id'])
api_name = record["plugin_name"].sub("custom_wizard_api_", "")
data = ::JSON.parse(record["value"])
data[:log_id] = record["key"].split("_").last
this_user = User.find_by(id: data["user_id"])
if this_user.nil?
data[:user_id] = nil
data[:username] = ""
@ -76,14 +75,17 @@ class CustomWizard::Api::LogEntry
data[:username] = this_user.username || ""
data[:userpath] = "/u/#{this_user.username_lower}/activity"
data[:name] = this_user.name || ""
data[:avatar_template] = "/user_avatar/default/#{this_user.username_lower}/97/#{this_user.uploaded_avatar_id}.png"
data[
:avatar_template
] = "/user_avatar/default/#{this_user.username_lower}/97/#{this_user.uploaded_avatar_id}.png"
end
self.new(api_name, data)
end
end
def self.clear(api_name)
PluginStoreRow.where("plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'").destroy_all
PluginStoreRow.where(
"plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'log_%'",
).destroy_all
end
end

Datei anzeigen

@ -30,7 +30,7 @@ class CustomWizard::Builder
@template.steps.each do |step_template|
next if !check_condition(step_template)
@wizard.append_step(step_template['id']) do |step|
@wizard.append_step(step_template["id"]) do |step|
step = check_if_permitted(step, step_template)
next if !step.permitted
@ -73,14 +73,15 @@ class CustomWizard::Builder
end
def check_condition(template)
if template['condition'].present?
result = CustomWizard::Mapper.new(
inputs: template['condition'],
if template["condition"].present?
result =
CustomWizard::Mapper.new(
inputs: template["condition"],
user: @wizard.user,
data: @wizard.current_submission&.fields_and_meta,
opts: {
multiple: true
}
multiple: true,
},
).perform
result.any?
@ -92,126 +93,121 @@ class CustomWizard::Builder
private
def mapper
CustomWizard::Mapper.new(
user: @wizard.user,
data: @wizard.current_submission&.fields_and_meta
)
CustomWizard::Mapper.new(user: @wizard.user, data: @wizard.current_submission&.fields_and_meta)
end
def append_field(step, step_template, field_template, build_opts)
params = {
id: field_template['id'],
type: field_template['type'],
required: field_template['required']
id: field_template["id"],
type: field_template["type"],
required: field_template["required"],
}
%w(label description image key validations min_length max_length char_counter tag_groups).each do |key|
params[key.to_sym] = field_template[key] if field_template[key]
end
%w[
label
description
image
key
validations
min_length
max_length
char_counter
tag_groups
].each { |key| params[key.to_sym] = field_template[key] if field_template[key] }
params[:value] = prefill_field(field_template, step_template)
if !build_opts[:reset] && (submission = @wizard.current_submission).present?
params[:value] = submission.fields[field_template['id']] if submission.fields[field_template['id']]
params[:value] = submission.fields[field_template["id"]] if submission.fields[
field_template["id"]
]
end
if field_template['type'] === 'group' && params[:value].present?
if field_template["type"] === "group" && params[:value].present?
params[:value] = params[:value].first
end
if field_template['type'] === 'checkbox'
params[:value] = standardise_boolean(params[:value])
params[:value] = standardise_boolean(params[:value]) if field_template["type"] === "checkbox"
params[:file_types] = field_template["file_types"] if field_template["type"] === "upload"
if %w[date time date_time].include?(field_template["type"])
params[:format] = field_template["format"]
end
if field_template['type'] === 'upload'
params[:file_types] = field_template['file_types']
if %w[category tag topic].include?(field_template["type"])
params[:limit] = field_template["limit"]
end
if ['date', 'time', 'date_time'].include?(field_template['type'])
params[:format] = field_template['format']
if field_template["type"] === "tag"
params[:can_create_tag] = standardise_boolean(field_template["can_create_tag"])
end
if %w[category tag topic].include?(field_template['type'])
params[:limit] = field_template['limit']
end
params[:property] = field_template["property"] if field_template["type"] === "category"
if field_template['type'] === 'tag'
params[:can_create_tag] = standardise_boolean(field_template['can_create_tag'])
end
params[:category] = field_template["category"] if field_template["type"] === "topic"
if field_template['type'] === 'category'
params[:property] = field_template['property']
end
if field_template['type'] === 'topic'
params[:category] = field_template['category']
end
if (content_inputs = field_template['content']).present?
content = CustomWizard::Mapper.new(
if (content_inputs = field_template["content"]).present?
content =
CustomWizard::Mapper.new(
inputs: content_inputs,
user: @wizard.user,
data: @wizard.current_submission&.fields_and_meta,
opts: {
with_type: true
}
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]
}
end
if content.present? && content[:result].present?
if content[:type] == "association"
content[:result] = content[:result].map { |item| { id: item[:key], name: item[:value] } }
end
params[:content] = content[:result]
end
end
if field_template['index'].present?
index = CustomWizard::Mapper.new(
inputs: field_template['index'],
if field_template["index"].present?
index =
CustomWizard::Mapper.new(
inputs: field_template["index"],
user: @wizard.user,
data: @wizard.current_submission&.fields_and_meta
data: @wizard.current_submission&.fields_and_meta,
).perform
params[:index] = index.to_i unless index.nil?
end
if field_template['description'].present?
if field_template["description"].present?
params[:description] = mapper.interpolate(
field_template['description'],
field_template["description"],
user: @wizard.user,
value: true,
wizard: true,
template: true
template: true,
)
end
if field_template['preview_template'].present?
preview_template = mapper.interpolate(
field_template['preview_template'],
if field_template["preview_template"].present?
preview_template =
mapper.interpolate(
field_template["preview_template"],
user: @wizard.user,
value: true,
wizard: true,
template: true
template: true,
)
params[:preview_template] = PrettyText.cook(preview_template)
end
if field_template['placeholder'].present?
if field_template["placeholder"].present?
params[:placeholder] = mapper.interpolate(
field_template['placeholder'],
field_template["placeholder"],
user: @wizard.user,
value: true,
wizard: true,
template: true
template: true,
)
end
@ -219,11 +215,11 @@ class CustomWizard::Builder
end
def prefill_field(field_template, step_template)
if (prefill = field_template['prefill']).present?
if (prefill = field_template["prefill"]).present?
CustomWizard::Mapper.new(
inputs: prefill,
user: @wizard.user,
data: @wizard.current_submission&.fields_and_meta
data: @wizard.current_submission&.fields_and_meta,
).perform
end
end
@ -231,13 +227,11 @@ class CustomWizard::Builder
def check_if_permitted(step, step_template)
step.permitted = true
if step_template['required_data']
step = ensure_required_data(step, step_template)
end
step = ensure_required_data(step, step_template) if step_template["required_data"]
if !step.permitted
if step_template['required_data_message']
step.permitted_message = step_template['required_data_message']
if step_template["required_data_message"]
step.permitted_message = step_template["required_data_message"]
end
end
@ -245,17 +239,18 @@ class CustomWizard::Builder
end
def add_step_attributes(step, step_template)
%w(index title banner key force_final).each do |attr|
%w[index title banner key force_final].each do |attr|
step.send("#{attr}=", step_template[attr]) if step_template[attr]
end
if step_template['description']
step.description = mapper.interpolate(
step_template['description'],
if step_template["description"]
step.description =
mapper.interpolate(
step_template["description"],
user: @wizard.user,
value: true,
wizard: true,
template: true
template: true,
)
step.description = PrettyText.cook(step.description)
end
@ -264,8 +259,8 @@ class CustomWizard::Builder
end
def append_step_fields(step, step_template, build_opts)
if step_template['fields'] && step_template['fields'].length
step_template['fields'].each do |field_template|
if step_template["fields"] && step_template["fields"].length
step_template["fields"].each do |field_template|
next if !check_condition(field_template)
append_field(step, step_template, field_template, build_opts)
end
@ -280,18 +275,18 @@ class CustomWizard::Builder
end
def save_permitted_params(step_template, params)
return unless step_template['permitted_params'].present?
return if step_template["permitted_params"].blank?
permitted_params = step_template['permitted_params']
permitted_params = step_template["permitted_params"]
permitted_data = {}
submission_key = nil
params_key = nil
submission = @wizard.current_submission
permitted_params.each do |pp|
pair = pp['pairs'].first
params_key = pair['key'].to_sym
submission_key = pair['value'].to_sym
pair = pp["pairs"].first
params_key = pair["key"].to_sym
submission_key = pair["value"].to_sym
if submission_key && params_key && params[params_key].present?
submission.permitted_param_keys << submission_key.to_s
@ -303,19 +298,15 @@ class CustomWizard::Builder
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
step_template["required_data"].each do |required|
pairs = required["pairs"].select { |pair| pair["key"].present? && pair["value"].present? }
if pairs.any? && !@wizard.current_submission.present?
step.permitted = false
break
end
pairs.each do |pair|
pair['key'] = @wizard.current_submission.fields[pair['key']]
end
pairs.each { |pair| pair["key"] = @wizard.current_submission.fields[pair["key"]] }
if !mapper.validate_pairs(pairs)
step.permitted = false
@ -328,25 +319,22 @@ class CustomWizard::Builder
def apply_step_handlers
CustomWizard::Builder.step_handlers.each do |handler|
if handler[:wizard_id] == @wizard.id
handler[:block].call(self)
end
handler[:block].call(self) if handler[:wizard_id] == @wizard.id
end
end
def run_step_actions
if @template.actions.present?
@template.actions.each do |action_template|
if action_template['run_after'] === updater.step.id
result = CustomWizard::Action.new(
if action_template["run_after"] === updater.step.id
result =
CustomWizard::Action.new(
action: action_template,
wizard: @wizard,
submission: @submission
submission: @submission,
).perform
if result.success?
@submission = result.submission
end
@submission = result.submission if result.success?
end
end
end

Datei anzeigen

@ -6,20 +6,20 @@ class ::CustomWizard::CustomField
attr_reader :id
ATTRS ||= ["name", "klass", "type", "serializers"]
REQUIRED ||= ["name", "klass", "type"]
ATTRS ||= %w[name klass type serializers]
REQUIRED ||= %w[name klass type]
NAMESPACE ||= "custom_wizard_custom_fields"
NAME_MIN_LENGTH ||= 3
CLASSES ||= {
topic: ["topic_view", "topic_list_item"],
topic: %w[topic_view topic_list_item],
group: ["basic_group"],
category: ["basic_category"],
post: ["post"]
post: ["post"],
}
TYPES ||= ["string", "boolean", "integer", "json"]
LIST_CACHE_KEY ||= 'custom_field_list'
TYPES ||= %w[string boolean integer json]
LIST_CACHE_KEY ||= "custom_field_list"
def self.serializers
CLASSES.values.flatten.uniq
@ -34,9 +34,7 @@ class ::CustomWizard::CustomField
value = data[attr]
if value.present?
send("#{attr}=", value)
end
send("#{attr}=", value) if value.present?
end
@subscription = CustomWizard::Subscription.new
@ -49,9 +47,7 @@ class ::CustomWizard::CustomField
data = {}
key = name
(ATTRS - ['name']).each do |attr|
data[attr] = send(attr)
end
(ATTRS - ["name"]).each { |attr| data[attr] = send(attr) }
if self.class.save_to_store(id, key, data)
self.class.invalidate_cache
@ -74,39 +70,38 @@ class ::CustomWizard::CustomField
break
end
if attr == 'serializers' && !value.is_a?(Array)
next
end
next if attr == "serializers" && !value.is_a?(Array)
if (attr == 'klass' && CLASSES.keys.exclude?(value.to_sym)) ||
(attr == 'serializers' && CLASSES[klass.to_sym].blank?)
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 == 'klass' && !@subscription.includes?(:custom_field, :klass, value)
if attr == "klass" && !@subscription.includes?(:custom_field, :klass, value)
add_error(I18n.t("wizard.custom_field.error.subscription_type", type: value))
end
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
add_error(I18n.t("#{i18n_key}.unsupported_serializers",
if attr == "serializers" && (unsupported = value - CLASSES[klass.to_sym]).length > 0
add_error(
I18n.t(
"#{i18n_key}.unsupported_serializers",
class: klass,
serializers: unsupported.join(", ")
))
serializers: unsupported.join(", "),
),
)
end
if attr == 'type' && TYPES.exclude?(value)
if attr == "type" && TYPES.exclude?(value)
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
end
if attr == 'type' && !@subscription.includes?(:custom_field, :type, value)
if attr == "type" && !@subscription.includes?(:custom_field, :type, value)
add_error(I18n.t("wizard.custom_field.error.subscription_type", type: value))
end
if attr == 'name'
unless value.is_a?(String)
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
end
if attr == "name"
add_error(I18n.t("#{i18n_key}.name_invalid", name: value)) unless value.is_a?(String)
if value.length < NAME_MIN_LENGTH
add_error(I18n.t("#{i18n_key}.name_too_short", name: value, min_length: NAME_MIN_LENGTH))
@ -117,8 +112,8 @@ class ::CustomWizard::CustomField
end
begin
@name = value.parameterize(separator: '_')
rescue
@name = value.parameterize(separator: "_")
rescue StandardError
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
end
end
@ -134,16 +129,15 @@ class ::CustomWizard::CustomField
end
def self.list
PluginStoreRow.where(plugin_name: NAMESPACE).map do |record|
create_from_store(record)
end
PluginStoreRow.where(plugin_name: NAMESPACE).map { |record| create_from_store(record) }
end
def self.cached_list
@custom_wizard_cached_fields ||= ::CustomWizard::Cache.wrap(LIST_CACHE_KEY) do
PluginStoreRow.where(plugin_name: NAMESPACE).map do |record|
create_from_store(record).as_json.with_indifferent_access
end
@custom_wizard_cached_fields ||=
::CustomWizard::Cache.wrap(LIST_CACHE_KEY) do
PluginStoreRow
.where(plugin_name: NAMESPACE)
.map { |record| create_from_store(record).as_json.with_indifferent_access }
end
end
@ -234,17 +228,12 @@ class ::CustomWizard::CustomField
external = []
CLASSES.keys.each do |klass|
meta_data = klass.to_s.classify.constantize.send('custom_field_meta_data')
meta_data = klass.to_s.classify.constantize.send("custom_field_meta_data")
if meta_data.present?
meta_data.each do |name, data|
unless list.any? { |field| field.name === name }
field = new(
'external',
name: name,
klass: klass,
type: data.type
)
field = new("external", name: name, klass: klass, type: data.type)
external.push(field)
end
end

Datei anzeigen

@ -1,7 +1,7 @@
# frozen_string_literal: true
module ::CustomWizard
PLUGIN_NAME ||= 'custom_wizard'
PLUGIN_NAME ||= "custom_wizard"
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME

Datei anzeigen

@ -1,5 +1,8 @@
# frozen_string_literal: true
module CustomWizard
class SprocketsFileNotFound < StandardError; end
class SprocketsEmptyPath < StandardError; end
class SprocketsFileNotFound < StandardError
end
class SprocketsEmptyPath < StandardError
end
end

Datei anzeigen

@ -3,11 +3,7 @@ module CustomWizardCustomFieldPreloader
def preload_custom_fields(objects, fields)
if objects.present? && cw_fields_enabled?
@cw_klass = objects.first.class.name.underscore
if cw_fields.any?
cw_fields.each do |field|
fields << field[:name]
end
end
cw_fields.each { |field| fields << field[:name] } if cw_fields.any?
end
super(objects, fields)
end

Datei anzeigen

@ -31,10 +31,11 @@ module CustomWizardCustomFieldSerializer
end
def get_cw_class
self.class.ancestors.map do |klass|
klass.to_s.underscore.gsub("_serializer", "")
end.select do |klass|
CustomWizard::CustomField.serializers.include?(klass)
end.first
self
.class
.ancestors
.map { |klass| klass.to_s.underscore.gsub("_serializer", "") }
.select { |klass| CustomWizard::CustomField.serializers.include?(klass) }
.first
end
end

Datei anzeigen

@ -4,9 +4,12 @@ module CustomWizardDiscourseTagging
def filter_allowed_tags(guardian, opts = {})
if opts[:for_input].respond_to?(:dig) && (groups = opts.dig(:for_input, :groups)).present?
tag_group_array = groups.split(",")
filtered_tags = TagGroup.includes(:tags).where(name: tag_group_array).map do |tag_group|
tag_group.tags.pluck(:name)
end.flatten
filtered_tags =
TagGroup
.includes(:tags)
.where(name: tag_group_array)
.map { |tag_group| tag_group.tags.pluck(:name) }
.flatten
opts[:only_tag_names] ||= []
opts[:only_tag_names].push(*filtered_tags)

Datei anzeigen

@ -1,11 +1,12 @@
# frozen_string_literal: true
module ExtraLocalesControllerCustomWizard
private def valid_bundle?(bundle)
super || begin
return false unless bundle =~ /wizard/ && request.referer =~ /\/w\//
super ||
begin
return false unless bundle =~ /wizard/ && request.referer =~ %r{/w/}
path = URI(request.referer).path
wizard_path = path.split('/w/').last
wizard_id = wizard_path.split('/').first
wizard_path = path.split("/w/").last
wizard_id = wizard_path.split("/").first
return true if wizard_id == "qunit"
CustomWizard::Template.exists?(wizard_id.underscore)
end

Datei anzeigen

@ -8,9 +8,7 @@ module CustomWizardGuardian
def wizard_can_edit_topic?(topic)
created_by_wizard = !!topic.wizard_submission_id
(
is_my_own?(topic) &&
created_by_wizard &&
can_see_topic?(topic) &&
is_my_own?(topic) && created_by_wizard && can_see_topic?(topic) &&
can_create_post_on_topic?(topic)
)
end

Datei anzeigen

@ -4,7 +4,7 @@ module InvitesControllerCustomWizard
if ::Wizard.user_requires_completion?(@user)
wizard_id = @user.redirect_to_wizard
if wizard_id && url != '/'
if wizard_id && url != "/"
CustomWizard::Wizard.set_wizard_redirect(@user, wizard_id, url)
url = "/w/#{wizard_id.dasherize}"
end

Datei anzeigen

@ -1,8 +1,7 @@
# frozen_string_literal: true
module CustomWizardUsersController
def account_created
if current_user.present? &&
(wizard = CustomWizard::Wizard.after_signup(current_user))
if current_user.present? && (wizard = CustomWizard::Wizard.after_signup(current_user))
return redirect_to "/w/#{wizard.id.dasherize}"
end
super

Datei anzeigen

@ -27,12 +27,9 @@ class CustomWizard::Field
:preview_template,
:placeholder
attr_accessor :index,
:step
attr_accessor :index, :step
REQUIRES_USER = %w[
upload
]
REQUIRES_USER = %w[upload]
def initialize(attrs)
@raw = attrs || {}
@ -64,9 +61,7 @@ class CustomWizard::Field
end
def default_value
if @type == 'checkbox'
false
end
false if @type == "checkbox"
end
def self.types
@ -77,82 +72,90 @@ class CustomWizard::Field
prefill: nil,
char_counter: nil,
validations: nil,
placeholder: nil
placeholder: nil,
},
textarea: {
min_length: nil,
max_length: nil,
prefill: nil,
char_counter: nil,
placeholder: nil
placeholder: nil,
},
composer: {
min_length: nil,
max_length: nil,
char_counter: nil,
placeholder: nil
placeholder: nil,
},
text_only: {
},
text_only: {},
composer_preview: {
preview_template: nil,
},
date: {
format: "YYYY-MM-DD"
format: "YYYY-MM-DD",
},
time: {
format: "HH:mm"
format: "HH:mm",
},
date_time: {
format: ""
format: "",
},
number: {
},
checkbox: {
},
number: {},
checkbox: {},
url: {
min_length: nil
min_length: nil,
},
upload: {
file_types: '.jpg,.jpeg,.png'
file_types: ".jpg,.jpeg,.png",
},
dropdown: {
prefill: nil,
content: nil
content: nil,
},
tag: {
limit: nil,
prefill: nil,
content: nil,
tag_groups: nil,
can_create_tag: false
can_create_tag: false,
},
category: {
limit: 1,
property: 'id',
property: "id",
prefill: nil,
content: nil
content: nil,
},
topic: {
limit: 1,
prefill: nil,
content: nil,
category: nil
category: nil,
},
group: {
prefill: nil,
content: nil
content: nil,
},
user_selector: {
},
user_selector: {}
}
end
def self.require_assets
Rails.logger.warn("Custom Wizard field regisration no longer requires asset registration. Support will be removed in v2.1.0.")
Rails.logger.warn(
"Custom Wizard field regisration no longer requires asset registration. Support will be removed in v2.1.0.",
)
@require_assets ||= {}
end
def self.register(type, plugin = nil, opts = {}, legacy_opts = {})
if opts.is_a?(Array)
Rails.logger.warn("Custom Wizard field regisration no longer requires asset registration. Support will be removed in v2.1.0.")
Rails.logger.warn(
"Custom Wizard field regisration no longer requires asset registration. Support will be removed in v2.1.0.",
)
require_assets[plugin] = opts
opts = legacy_opts

Datei anzeigen

@ -8,30 +8,28 @@ class CustomWizard::Log
PAGE_LIMIT = 100
def initialize(attrs)
@date = attrs['date']
@action = attrs['action']
@message = attrs['message']
@wizard_id = attrs['wizard_id']
@username = attrs['username']
@date = attrs["date"]
@action = attrs["action"]
@message = attrs["message"]
@wizard_id = attrs["wizard_id"]
@username = attrs["username"]
end
def self.create(wizard_id, action, username, message, date = Time.now)
log_id = SecureRandom.hex(12)
PluginStore.set('custom_wizard_log',
PluginStore.set(
"custom_wizard_log",
log_id.to_s,
{
date: date,
wizard_id: wizard_id,
action: action,
username: username,
message: message
}
{ date: date, wizard_id: wizard_id, action: action, username: username, message: message },
)
end
def self.list_query(wizard_id = nil)
query = PluginStoreRow.where("plugin_name = 'custom_wizard_log' AND (value::json->'date') IS NOT NULL")
query =
PluginStoreRow.where(
"plugin_name = 'custom_wizard_log' AND (value::json->'date') IS NOT NULL",
)
query = query.where("(value::json->>'wizard_id') = ?", wizard_id) if wizard_id
query.order("value::json->>'date' DESC")
end
@ -43,9 +41,7 @@ class CustomWizard::Log
result = OpenStruct.new(logs: [], total: nil)
result.total = logs.size
result.logs = logs.limit(limit)
.offset(page * limit)
.map { |r| self.new(JSON.parse(r.value)) }
result.logs = logs.limit(limit).offset(page * limit).map { |r| self.new(JSON.parse(r.value)) }
result
end

Datei anzeigen

@ -2,45 +2,29 @@
class CustomWizard::Mapper
attr_accessor :inputs, :data, :user
USER_FIELDS = [
'name',
'username',
'date_of_birth',
'title',
'locale',
'trust_level',
'email'
]
USER_FIELDS = %w[name username date_of_birth title locale trust_level email]
USER_OPTION_FIELDS = [
'email_level',
'email_messages_level',
'email_digests'
]
USER_OPTION_FIELDS = %w[email_level email_messages_level email_digests]
PROFILE_FIELDS = [
'location',
'website',
'bio_raw'
]
PROFILE_FIELDS = %w[location website bio_raw]
def self.user_fields
USER_FIELDS + USER_OPTION_FIELDS + PROFILE_FIELDS
end
OPERATORS = {
equal: '==',
equal: "==",
not_equal: "!=",
greater: '>',
less: '<',
greater_or_equal: '>=',
less_or_equal: '<=',
regex: '=~',
greater: ">",
less: "<",
greater_or_equal: ">=",
less_or_equal: "<=",
regex: "=~",
is: {
present: "present?",
true: "==",
false: "=="
}
false: "==",
},
}
def initialize(params)
@ -55,12 +39,12 @@ class CustomWizard::Mapper
perform_result = multiple ? [] : nil
inputs.each do |input|
input_type = input['type']
pairs = input['pairs']
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']
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)
@ -72,7 +56,7 @@ class CustomWizard::Mapper
end
end
if input_type === 'validation'
if input_type === "validation"
result = build_result(validate_pairs(pairs), input_type)
if multiple
@ -83,7 +67,7 @@ class CustomWizard::Mapper
end
end
if input_type === 'association'
if input_type === "association"
result = build_result(map_pairs(pairs), input_type)
if multiple
@ -100,10 +84,7 @@ class CustomWizard::Mapper
def build_result(result, type)
if @opts[:with_type]
{
type: type,
result: result
}
{ type: type, result: result }
else
result
end
@ -111,10 +92,10 @@ class CustomWizard::Mapper
def validate_pairs(pairs)
pairs.all? do |pair|
connector = pair['connector']
connector = pair["connector"]
operator = map_operator(connector)
key = map_field(pair['key'], pair['key_type'])
value = cast_value(map_field(pair['value'], pair['value_type']), key, connector)
key = map_field(pair["key"], pair["key_type"])
value = cast_value(map_field(pair["value"], pair["value_type"]), key, connector)
begin
validation_result(key, value, operator)
rescue NoMethodError
@ -124,7 +105,7 @@ class CustomWizard::Mapper
end
def cast_value(value, key, connector)
if connector == 'regex'
if connector == "regex"
Regexp.new(value)
else
if key.is_a?(String)
@ -143,7 +124,7 @@ class CustomWizard::Mapper
if operator.is_a?(Hash) && (operator = operator[value.to_sym]).present?
if value == "present"
result = key.public_send(operator)
elsif ["true", "false"].include?(value)
elsif %w[true false].include?(value)
result = bool(key).public_send(operator, bool(value))
end
elsif [key, value, operator].all? { |i| !i.nil? }
@ -152,7 +133,7 @@ class CustomWizard::Mapper
result = false
end
if operator == '=~'
if operator == "=~"
result.nil? ? false : true
else
result
@ -163,22 +144,17 @@ class CustomWizard::Mapper
result = []
pairs.each do |pair|
key = map_field(pair['key'], pair['key_type'])
value = map_field(pair['value'], pair['value_type'])
key = map_field(pair["key"], pair["key_type"])
value = map_field(pair["value"], pair["value_type"])
if key && value
result.push(
key: key,
value: value
)
end
result.push(key: key, value: value) if key && value
end
result
end
def map_operator(connector)
OPERATORS[connector.to_sym] || '=='
OPERATORS[connector.to_sym] || "=="
end
def map_field(value, type)
@ -214,7 +190,7 @@ class CustomWizard::Mapper
user.send(value)
elsif USER_OPTION_FIELDS.include?(value)
user.user_option.send(value)
elsif value.include?('avatar')
elsif value.include?("avatar")
get_avatar_url(value)
else
nil
@ -223,7 +199,7 @@ class CustomWizard::Mapper
def map_user_field_options(value)
if value.include?(User::USER_FIELD_PREFIX)
if field = UserField.find_by(id: value.split('_').last)
if field = UserField.find_by(id: value.split("_").last)
field.user_field_options.map(&:value)
end
end
@ -232,22 +208,18 @@ class CustomWizard::Mapper
def interpolate(string, opts = { user: true, wizard: true, value: true, template: false })
return string if string.blank? || string.frozen?
if opts[:user] && @user.present?
string.gsub!(/u\{(.*?)\}/) { |match| map_user_field($1) || '' }
end
string.gsub!(/u\{(.*?)\}/) { |match| map_user_field($1) || "" } if opts[:user] && @user.present?
if opts[:wizard]
string.gsub!(/w\{(.*?)\}/) { |match| recurse(data, [*$1.split('.')]) || '' }
end
string.gsub!(/w\{(.*?)\}/) { |match| recurse(data, [*$1.split(".")]) || "" } if opts[:wizard]
if opts[:value]
string.gsub!(/v\{(.*?)\}/) do |match|
attrs = $1.split(':')
attrs = $1.split(":")
key = attrs.first
format = attrs.last if attrs.length > 1
result = ''
result = ""
if key == 'time'
if key == "time"
time_format = format.present? ? format : "%B %-d, %Y"
result = Time.now.strftime(time_format)
end
@ -281,10 +253,10 @@ class CustomWizard::Mapper
end
def get_avatar_url(value)
parts = value.split('.')
parts = value.split(".")
valid_sizes = Discourse.avatar_sizes.to_a
if value === 'avatar' || parts.size === 1 || valid_sizes.exclude?(parts.last.to_i)
if value === "avatar" || parts.size === 1 || valid_sizes.exclude?(parts.last.to_i)
user.small_avatar_url
else
user.avatar_template_url.gsub("{size}", parts.last)

Datei anzeigen

@ -8,7 +8,7 @@ class CustomWizard::RealtimeValidation
types: [:text],
component: "similar-topics-validator",
backend: true,
required_params: []
}
required_params: [],
},
}
end

Datei anzeigen

@ -1,8 +1,6 @@
# frozen_string_literal: true
class CustomWizard::RealtimeValidation::Result
attr_accessor :type,
:items,
:serializer_opts
attr_accessor :type, :items, :serializer_opts
def initialize(type)
@type = type

Datei anzeigen

@ -27,9 +27,7 @@ class CustomWizard::RealtimeValidation::SimilarTopics
result = CustomWizard::RealtimeValidation::Result.new(:similar_topic)
if title.length < SiteSetting.min_title_similar_length
return result
end
return result if title.length < SiteSetting.min_title_similar_length
topics = Topic.similar_to(title, raw, user).to_a
topics.select! { |t| categories.include?(t.category.id.to_s) } if categories.present?

Datei anzeigen

@ -3,8 +3,7 @@
class CustomWizard::Step
include ActiveModel::SerializerSupport
attr_reader :id,
:updater
attr_reader :id, :updater
attr_accessor :index,
:title,

Datei anzeigen

@ -14,18 +14,14 @@ class CustomWizard::StepUpdater
end
def update
if SiteSetting.custom_wizard_enabled &&
@step.present? &&
@step.updater.present? &&
success?
if SiteSetting.custom_wizard_enabled && @step.present? && @step.updater.present? && success?
@step.updater.call(self)
CustomWizard::UserHistory.create(
action: CustomWizard::UserHistory.actions[:step],
actor_id: @wizard.actor_id,
context: @wizard.id,
subject: @step.id
subject: @step.id,
)
else
false

Datei anzeigen

@ -4,31 +4,25 @@ class CustomWizard::Submission
PAGE_LIMIT = 50
KEY ||= "submissions"
META ||= %w(updated_at submitted_at route_to redirect_on_complete redirect_to)
META ||= %w[updated_at submitted_at route_to redirect_on_complete redirect_to]
attr_reader :id,
:wizard
attr_reader :id, :wizard
attr_accessor :fields,
:permitted_param_keys
attr_accessor :fields, :permitted_param_keys
META.each do |attr|
class_eval { attr_accessor attr }
end
META.each { |attr| class_eval { attr_accessor attr } }
def initialize(wizard, data = {})
@wizard = wizard
data = (data || {}).with_indifferent_access
@id = data['id'] || SecureRandom.hex(12)
non_field_keys = META + ['id']
@id = data["id"] || SecureRandom.hex(12)
non_field_keys = META + ["id"]
@fields = data.except(*non_field_keys) || {}
META.each do |attr|
send("#{attr}=", data[attr]) if data[attr]
end
META.each { |attr| send("#{attr}=", data[attr]) if data[attr] }
@permitted_param_keys = data['permitted_param_keys'] || []
@permitted_param_keys = data["permitted_param_keys"] || []
end
def save
@ -49,8 +43,7 @@ class CustomWizard::Submission
end
def validate_field_key(key)
wizard.field_ids.include?(key) ||
wizard.action_ids.include?(key) ||
wizard.field_ids.include?(key) || wizard.action_ids.include?(key) ||
permitted_param_keys.include?(key)
end
@ -71,9 +64,7 @@ class CustomWizard::Submission
end
def data_to_save(submission)
data = {
id: submission.id
}
data = { id: submission.id }
data.merge!(submission.fields_and_meta)
@ -103,16 +94,21 @@ class CustomWizard::Submission
def self.cleanup_incomplete_submissions(wizard)
all_submissions = list(wizard)
sorted_submissions = all_submissions.submissions.sort_by do |submission|
zero_epoch_time = DateTime.strptime("0", '%s')
sorted_submissions =
all_submissions
.submissions
.sort_by do |submission|
zero_epoch_time = DateTime.strptime("0", "%s")
[
submission.submitted_at ? Time.iso8601(submission.submitted_at) : zero_epoch_time,
submission.updated_at ? Time.iso8601(submission.updated_at) : zero_epoch_time
submission.updated_at ? Time.iso8601(submission.updated_at) : zero_epoch_time,
]
end.reverse
end
.reverse
has_incomplete = false
valid_submissions = sorted_submissions.select do |submission|
valid_submissions =
sorted_submissions.select do |submission|
to_be_included = submission.submitted_at || !has_incomplete
has_incomplete = true if !submission.submitted_at

Datei anzeigen

@ -2,128 +2,129 @@
require "discourse_subscription_client"
class CustomWizard::Subscription
PRODUCT_HIERARCHY = %w[
community
standard
business
]
PRODUCT_HIERARCHY = %w[community standard business]
def self.attributes
{
wizard: {
required: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
standard: ["*"],
business: ["*"],
community: ["*"],
},
permitted: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*', "!#{CustomWizard::Wizard::GUEST_GROUP_ID}"]
standard: ["*"],
business: ["*"],
community: ["*", "!#{CustomWizard::Wizard::GUEST_GROUP_ID}"],
},
restart_on_revisit: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
}
standard: ["*"],
business: ["*"],
community: ["*"],
},
},
step: {
condition: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
standard: ["*"],
business: ["*"],
community: ["*"],
},
required_data: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
standard: ["*"],
business: ["*"],
community: ["*"],
},
permitted_params: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
}
standard: ["*"],
business: ["*"],
community: ["*"],
},
},
field: {
condition: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
standard: ["*"],
business: ["*"],
community: ["*"],
},
type: {
none: ['text', 'textarea', 'text_only', 'date', 'time', 'date_time', 'number', 'checkbox', 'dropdown', 'upload'],
standard: ['*'],
business: ['*'],
community: ['*']
none: %w[text textarea text_only date time date_time number checkbox dropdown upload],
standard: ["*"],
business: ["*"],
community: ["*"],
},
realtime_validations: {
none: [],
standard: ['*'],
business: ['*'],
community: ['*']
}
standard: ["*"],
business: ["*"],
community: ["*"],
},
},
action: {
type: {
none: ['create_topic', 'update_profile', 'open_composer', 'route_to'],
standard: ['create_topic', 'update_profile', 'open_composer', 'route_to', 'send_message', 'watch_categories', 'watch_tags', 'add_to_group'],
business: ['*'],
community: ['*']
}
none: %w[create_topic update_profile open_composer route_to],
standard: %w[
create_topic
update_profile
open_composer
route_to
send_message
watch_categories
watch_tags
add_to_group
],
business: ["*"],
community: ["*"],
},
},
custom_field: {
klass: {
none: ['topic', 'post'],
standard: ['topic', 'post'],
business: ['*'],
community: ['*']
none: %w[topic post],
standard: %w[topic post],
business: ["*"],
community: ["*"],
},
type: {
none: ['string', 'boolean', 'integer'],
standard: ['string', 'boolean', 'integer'],
business: ['*'],
community: ['*']
}
none: %w[string boolean integer],
standard: %w[string boolean integer],
business: ["*"],
community: ["*"],
},
},
api: {
all: {
none: [],
standard: [],
business: ['*'],
community: ['*']
}
}
business: ["*"],
community: ["*"],
},
},
}
end
attr_accessor :product_id,
:product_slug
attr_accessor :product_id, :product_slug
def initialize(update = false)
if update
::DiscourseSubscriptionClient::Subscriptions.update
end
::DiscourseSubscriptionClient::Subscriptions.update if update
result = ::DiscourseSubscriptionClient.find_subscriptions("discourse-custom-wizard")
if result&.any?
ids_and_slugs = result.subscriptions.map do |subscription|
{
id: subscription.product_id,
slug: result.products[subscription.product_id]
}
ids_and_slugs =
result.subscriptions.map do |subscription|
{ id: subscription.product_id, slug: result.products[subscription.product_id] }
end
id_and_slug = ids_and_slugs.sort do |a, b|
PRODUCT_HIERARCHY.index(b[:slug]) - PRODUCT_HIERARCHY.index(a[:slug])
end.first
id_and_slug =
ids_and_slugs
.sort { |a, b| PRODUCT_HIERARCHY.index(b[:slug]) - PRODUCT_HIERARCHY.index(a[:slug]) }
.first
@product_id = id_and_slug[:id]
@product_slug = id_and_slug[:slug]
@ -182,7 +183,8 @@ class CustomWizard::Subscription
# TODO candidate for removal once code that depends on it externally is no longer used.
def self.client_installed?
defined?(DiscourseSubscriptionClient) == 'constant' && DiscourseSubscriptionClient.class == Module
defined?(DiscourseSubscriptionClient) == "constant" &&
DiscourseSubscriptionClient.class == Module
end
def self.subscribed?
@ -219,10 +221,12 @@ class CustomWizard::Subscription
end
def mapped_output(value)
value.reduce([]) do |result, v|
value
.reduce([]) do |result, v|
## We can only validate mapped assignment values at the moment
result << v["output"] if v.is_a?(Hash) && v["type"] === "assignment"
result
end.flatten
end
.flatten
end
end

Datei anzeigen

@ -6,15 +6,12 @@ class CustomWizard::Template
AFTER_SIGNUP_CACHE_KEY ||= "after_signup_wizard_ids"
AFTER_TIME_CACHE_KEY ||= "after_time_wizard_ids"
attr_reader :data,
:opts,
:steps,
:actions
attr_reader :data, :opts, :steps, :actions
def initialize(data)
@data = data
@steps = data['steps'] || []
@actions = data['actions'] || []
@steps = data["steps"] || []
@actions = data["actions"] || []
end
def save(opts = {})
@ -64,7 +61,11 @@ class CustomWizard::Template
ensure_wizard_upload_references!(wizard_id)
PluginStore.remove(CustomWizard::PLUGIN_NAME, wizard.id)
clear_user_wizard_redirect(wizard_id, after_time: !!wizard.after_time)
related_custom_fields = CategoryCustomField.where(name: 'create_topic_wizard', value: wizard.name.parameterize(separator: "_"))
related_custom_fields =
CategoryCustomField.where(
name: "create_topic_wizard",
value: wizard.name.parameterize(separator: "_"),
)
related_custom_fields.destroy_all
end
@ -74,7 +75,7 @@ class CustomWizard::Template
end
def self.exists?(wizard_id)
PluginStoreRow.exists?(plugin_name: 'custom_wizard', key: wizard_id)
PluginStoreRow.exists?(plugin_name: "custom_wizard", key: wizard_id)
end
def self.list(setting: nil, query_str: nil, order: :id)
@ -82,15 +83,13 @@ class CustomWizard::Template
query += " AND (value::json ->> '#{setting}')::boolean IS TRUE" if setting
query += " #{query_str}" if query_str
PluginStoreRow.where(query).order(order)
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?
if attrs.present? && attrs.is_a?(Hash) && attrs["id"].present? && attrs["name"].present?
result.push(attrs)
end
@ -99,25 +98,24 @@ class CustomWizard::Template
end
def self.clear_user_wizard_redirect(wizard_id, after_time: false)
UserCustomField.where(name: 'redirect_to_wizard', value: wizard_id).destroy_all
UserCustomField.where(name: "redirect_to_wizard", value: wizard_id).destroy_all
if after_time
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id)
end
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard_id) if after_time
end
def self.after_signup_ids
::CustomWizard::Cache.wrap(AFTER_SIGNUP_CACHE_KEY) do
list(setting: 'after_signup').map { |t| t['id'] }
list(setting: "after_signup").map { |t| t["id"] }
end
end
def self.after_time_ids
::CustomWizard::Cache.wrap(AFTER_TIME_CACHE_KEY) do
list(
setting: 'after_time',
query_str: "AND (value::json ->> 'after_time_scheduled')::timestamp < '#{Time.now}'::timestamp"
).map { |t| t['id'] }
setting: "after_time",
query_str:
"AND (value::json ->> 'after_time_scheduled')::timestamp < '#{Time.now}'::timestamp",
).map { |t| t["id"] }
end
end
@ -137,7 +135,7 @@ class CustomWizard::Template
UploadReference.ensure_exist!(
upload_ids: wizard_upload_ids,
target_type: "PluginStoreRow",
target_id: wizard_record.id
target_id: wizard_record.id,
)
end
end
@ -151,15 +149,11 @@ class CustomWizard::Template
def prepare_data
@data[:steps].each do |step|
if step[:raw_description]
step[:description] = step[:raw_description]
end
step[:description] = step[:raw_description] if step[:raw_description]
remove_non_mapped_index(step)
step[:fields].each do |field|
remove_non_mapped_index(field)
end
step[:fields].each { |field| remove_non_mapped_index(field) }
end
end
@ -191,9 +185,7 @@ class CustomWizard::Template
end
def remove_non_mapped_index(object)
if !object[:index].is_a?(Array)
object.delete(:index)
end
object.delete(:index) if !object[:index].is_a?(Array)
end
def ensure_wizard_upload_references!

Datei anzeigen

@ -15,26 +15,18 @@ class CustomWizard::UserHistory
end
def self.actions
@actions ||=
Enum.new(
step: UserHistory.actions[:custom_wizard_step]
)
@actions ||= Enum.new(step: UserHistory.actions[:custom_wizard_step])
end
def self.where_opts(actor_id, action, context, subject)
opts = {
context: context
}
opts = { context: context }
opts[:action] = action if action
opts[:subject] = subject if subject
add_actor(opts, actor_id)
end
def self.create_opts(actor_id, action, context, subject)
opts = {
action: action,
context: context
}
opts = { action: action, context: context }
opts[:subject] = subject if subject
add_actor(opts, actor_id)
end

Datei anzeigen

@ -48,12 +48,7 @@ class CustomWizard::TemplateValidator
end
def self.required
{
wizard: ['id', 'name', 'steps'],
step: ['id'],
field: ['id', 'type'],
action: ['id', 'type']
}
{ wizard: %w[id name steps], step: ["id"], field: %w[id type], action: %w[id type] }
end
private
@ -71,7 +66,8 @@ class CustomWizard::TemplateValidator
value = object[property]
if !@subscription.includes?(type, property.to_sym, value)
errors.add :base, I18n.t("wizard.validation.subscription", type: type.to_s, property: property)
errors.add :base,
I18n.t("wizard.validation.subscription", type: type.to_s, property: property)
end
end
end
@ -83,9 +79,9 @@ class CustomWizard::TemplateValidator
end
def validate_guests(object, type)
guests_permitted = @data[:permitted] && @data[:permitted].any? do |m|
m["output"]&.include?(CustomWizard::Wizard::GUEST_GROUP_ID)
end
guests_permitted =
@data[:permitted] &&
@data[:permitted].any? { |m| m["output"]&.include?(CustomWizard::Wizard::GUEST_GROUP_ID) }
return unless guests_permitted
if type === :action && CustomWizard::Action::REQUIRES_USER.include?(object[:type])
@ -100,11 +96,14 @@ class CustomWizard::TemplateValidator
def validate_after_signup
return unless ActiveRecord::Type::Boolean.new.cast(@data[:after_signup])
other_after_signup = CustomWizard::Template.list(setting: 'after_signup')
.select { |template| template['id'] != @data[:id] }
other_after_signup =
CustomWizard::Template
.list(setting: "after_signup")
.select { |template| template["id"] != @data[:id] }
if other_after_signup.any?
errors.add :base, I18n.t("wizard.validation.after_signup", wizard_id: other_after_signup.first['id'])
errors.add :base,
I18n.t("wizard.validation.after_signup", wizard_id: other_after_signup.first["id"])
end
end
@ -132,20 +131,16 @@ class CustomWizard::TemplateValidator
end
def validate_liquid_template(object, type)
%w[
description
raw_description
placeholder
preview_template
post_template
].each do |field|
%w[description raw_description placeholder preview_template post_template].each do |field|
if template = object[field]
result = is_liquid_template_valid?(template)
unless "valid" == result
error = I18n.t("wizard.validation.liquid_syntax_error",
error =
I18n.t(
"wizard.validation.liquid_syntax_error",
attribute: "#{object[:id]}.#{field}",
message: result
message: result,
)
errors.add :base, error
end
@ -156,7 +151,7 @@ class CustomWizard::TemplateValidator
def is_liquid_template_valid?(template)
begin
Liquid::Template.parse(template)
'valid'
"valid"
rescue Liquid::SyntaxError => error
error.message
end

Datei anzeigen

@ -1,5 +1,5 @@
# frozen_string_literal: true
require 'addressable/uri'
require "addressable/uri"
class ::CustomWizard::UpdateValidator
attr_reader :updater
@ -9,13 +9,11 @@ class ::CustomWizard::UpdateValidator
end
def perform
updater.step.fields.each do |field|
validate_field(field)
end
updater.step.fields.each { |field| validate_field(field) }
end
def validate_field(field)
return if field.type == 'text_only'
return if field.type == "text_only"
field_id = field.id.to_s
value = @updater.submission[field_id]
@ -29,43 +27,48 @@ class ::CustomWizard::UpdateValidator
format = field.format
if required && !value
@updater.errors.add(field_id, I18n.t('wizard.field.required', label: label))
@updater.errors.add(field_id, I18n.t("wizard.field.required", label: label))
end
if value.is_a?(String) && (stripped_length = value.strip.length) > 0
if min_length.present? && stripped_length < min_length.to_i
@updater.errors.add(field_id, I18n.t('wizard.field.too_short', label: label, min: min_length.to_i))
@updater.errors.add(
field_id,
I18n.t("wizard.field.too_short", label: label, min: min_length.to_i),
)
end
if max_length.present? && stripped_length > max_length.to_i
@updater.errors.add(field_id, I18n.t('wizard.field.too_long', label: label, max: max_length.to_i))
@updater.errors.add(
field_id,
I18n.t("wizard.field.too_long", label: label, max: max_length.to_i),
)
end
end
if is_url_type(field) && value.present? && !check_if_url(value)
@updater.errors.add(field_id, I18n.t('wizard.field.not_url', label: label))
@updater.errors.add(field_id, I18n.t("wizard.field.not_url", label: label))
end
if type === 'checkbox'
@updater.submission[field_id] = standardise_boolean(value)
@updater.submission[field_id] = standardise_boolean(value) if type === "checkbox"
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 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))
if %w[date date_time].include?(type) && value.present? && !validate_date(value, format)
@updater.errors.add(field_id, I18n.t("wizard.field.invalid_date"))
end
if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value, format)
@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'))
if type === "time" && value.present? && !validate_time(value)
@updater.errors.add(field_id, I18n.t("wizard.field.invalid_time"))
end
self.class.field_validators.each do |validator|
if type === validator[:type]
validator[:block].call(field, value, @updater)
end
validator[:block].call(field, value, @updater) if type === validator[:type]
end
end
@ -85,9 +88,10 @@ class ::CustomWizard::UpdateValidator
private
def validate_file_type(value, file_types)
file_types.split(',')
.map { |t| t.gsub('.', '') }
.include?(File.extname(value['original_filename'])[1..-1])
file_types
.split(",")
.map { |t| t.gsub(".", "") }
.include?(File.extname(value["original_filename"])[1..-1])
end
def validate_date(value, format)
@ -104,14 +108,14 @@ class ::CustomWizard::UpdateValidator
end
def is_text_type(field)
['text', 'textarea', 'composer'].include? field.type
%w[text textarea composer].include? field.type
end
def is_url_type(field)
['url'].include? field.type
["url"].include? field.type
end
SCHEMES ||= %w(http https)
SCHEMES ||= %w[http https]
def check_if_url(url)
parsed = Addressable::URI.parse(url) or return false

Datei anzeigen

@ -1,8 +1,8 @@
# frozen_string_literal: true
require_dependency 'wizard/step'
require_dependency 'wizard/field'
require_dependency 'wizard/step_updater'
require_dependency 'wizard/builder'
require_dependency "wizard/step"
require_dependency "wizard/field"
require_dependency "wizard/step_updater"
require_dependency "wizard/builder"
class CustomWizard::Wizard
include ActiveModel::SerializerSupport
@ -47,44 +47,40 @@ class CustomWizard::Wizard
attrs = attrs.with_indifferent_access
@id = attrs['id']
@name = attrs['name']
@background = attrs['background']
@save_submissions = cast_bool(attrs['save_submissions'])
@multiple_submissions = cast_bool(attrs['multiple_submissions'])
@prompt_completion = cast_bool(attrs['prompt_completion'])
@restart_on_revisit = cast_bool(attrs['restart_on_revisit'])
@resume_on_revisit = cast_bool(attrs['resume_on_revisit'])
@after_signup = cast_bool(attrs['after_signup'])
@after_time = cast_bool(attrs['after_time'])
@after_time_scheduled = attrs['after_time_scheduled']
@required = cast_bool(attrs['required'])
@permitted = attrs['permitted'] || nil
@theme_id = attrs['theme_id']
@id = attrs["id"]
@name = attrs["name"]
@background = attrs["background"]
@save_submissions = cast_bool(attrs["save_submissions"])
@multiple_submissions = cast_bool(attrs["multiple_submissions"])
@prompt_completion = cast_bool(attrs["prompt_completion"])
@restart_on_revisit = cast_bool(attrs["restart_on_revisit"])
@resume_on_revisit = cast_bool(attrs["resume_on_revisit"])
@after_signup = cast_bool(attrs["after_signup"])
@after_time = cast_bool(attrs["after_time"])
@after_time_scheduled = attrs["after_time_scheduled"]
@required = cast_bool(attrs["required"])
@permitted = attrs["permitted"] || nil
@theme_id = attrs["theme_id"]
if attrs['theme'].present?
theme = ::Theme.find_by(name: attrs['theme'])
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 = @all_step_ids = attrs['steps'].map { |s| s['id'] }
if attrs["steps"].present?
@step_ids = @all_step_ids = attrs["steps"].map { |s| s["id"] }
@field_ids = []
attrs['steps'].each do |step|
if step['fields'].present?
step['fields'].each do |field|
@field_ids << field['id']
end
end
attrs["steps"].each do |step|
step["fields"].each { |field| @field_ids << field["id"] } if step["fields"].present?
end
end
@actions = attrs['actions'] || []
@action_ids = @actions.map { |a| a['id'] }
@actions = attrs["actions"] || []
@action_ids = @actions.map { |a| a["id"] }
@template = attrs
end
@ -137,13 +133,9 @@ class CustomWizard::Wizard
step.index = index
if index === (steps.length - 1)
step.conditional_final_step = true
end
step.conditional_final_step = true if index === (steps.length - 1)
if index === (all_step_ids.length - 1)
step.last_step = true
end
step.last_step = true if index === (all_step_ids.length - 1)
if !@restart_on_revisit && step.previous && step.previous.id === last_completed_step_id
@start = step.id
@ -154,12 +146,16 @@ class CustomWizard::Wizard
def last_completed_step_id
return nil unless actor_id && unfinished?
last_completed_step = CustomWizard::UserHistory.where(
last_completed_step =
CustomWizard::UserHistory
.where(
actor_id: actor_id,
action: CustomWizard::UserHistory.actions[:step],
context: id,
subject: all_step_ids
).order("created_at").last
subject: all_step_ids,
)
.order("created_at")
.last
last_completed_step&.subject
end
@ -178,11 +174,12 @@ class CustomWizard::Wizard
return nil unless actor_id
return false if last_submission&.submitted?
most_recent = CustomWizard::UserHistory.where(
actor_id: actor_id,
action: CustomWizard::UserHistory.actions[:step],
context: id,
).distinct.order('updated_at DESC').first
most_recent =
CustomWizard::UserHistory
.where(actor_id: actor_id, action: CustomWizard::UserHistory.actions[:step], context: id)
.distinct
.order("updated_at DESC")
.first
if most_recent && most_recent.subject == "reset"
false
@ -197,10 +194,11 @@ class CustomWizard::Wizard
return nil unless actor_id
return true if last_submission&.submitted?
history = CustomWizard::UserHistory.where(
history =
CustomWizard::UserHistory.where(
actor_id: actor_id,
action: CustomWizard::UserHistory.actions[:step],
context: id
context: id,
)
if after_time && multiple_submissions
@ -216,26 +214,27 @@ class CustomWizard::Wizard
return true if user && ((always_allow_admin && user.admin?) || permitted.blank?)
return false if !user && permitted.blank?
mapper = CustomWizard::Mapper.new(
mapper =
CustomWizard::Mapper.new(
inputs: permitted,
user: user,
opts: {
with_type: true,
multiple: true
}
multiple: true,
},
).perform
return true if mapper.blank?
mapper.all? do |m|
if !user
m[:type] === 'assignment' && [*m[:result]].include?(GUEST_GROUP_ID)
m[:type] === "assignment" && [*m[:result]].include?(GUEST_GROUP_ID)
else
if m[:type] === 'assignment'
if m[:type] === "assignment"
[*m[:result]].include?(GUEST_GROUP_ID) ||
[*m[:result]].include?(Group::AUTO_GROUPS[:everyone]) ||
GroupUser.exists?(group_id: m[:result], user_id: user.id)
elsif m[:type] === 'validation'
elsif m[:type] === "validation"
m[:result]
else
true
@ -259,7 +258,7 @@ class CustomWizard::Wizard
action: CustomWizard::UserHistory.actions[:step],
actor_id: actor_id,
context: id,
subject: "reset"
subject: "reset",
)
end
@ -275,11 +274,9 @@ class CustomWizard::Wizard
@action_ids = []
@actions.each do |action|
if action['run_after'].blank? ||
action['run_after'] === 'wizard_completion' ||
step_ids.include?(action['run_after'])
@action_ids << action['id']
if action["run_after"].blank? || action["run_after"] === "wizard_completion" ||
step_ids.include?(action["run_after"])
@action_ids << action["id"]
end
end
end
@ -293,7 +290,8 @@ class CustomWizard::Wizard
end
def current_submission
@current_submission ||= begin
@current_submission ||=
begin
if submissions.present?
unsubmitted = submissions.select { |submission| !submission.submitted_at }
unsubmitted.present? ? unsubmitted.first : CustomWizard::Submission.new(self)
@ -317,9 +315,7 @@ class CustomWizard::Wizard
def cleanup_on_skip!
remove_user_redirect
if current_submission.present?
current_submission.remove
end
current_submission.remove if current_submission.present?
reset
end
@ -328,7 +324,7 @@ class CustomWizard::Wizard
return if user.blank?
if id == user.redirect_to_wizard
user.custom_fields.delete('redirect_to_wizard')
user.custom_fields.delete("redirect_to_wizard")
user.save_custom_fields(true)
end
end
@ -344,42 +340,33 @@ class CustomWizard::Wizard
def self.list(user, template_opts = {}, not_completed = false)
return [] unless user
CustomWizard::Template.list(**template_opts).reduce([]) do |result, template|
CustomWizard::Template
.list(**template_opts)
.reduce([]) do |result, template|
wizard = new(template, user)
result.push(wizard) if wizard.permitted? && (
!not_completed || !wizard.completed?
)
result.push(wizard) if wizard.permitted? && (!not_completed || !wizard.completed?)
result
end
end
def self.after_signup(user)
wizards = list(
wizards =
list(
user,
{
setting: 'after_signup',
order: "(value::json ->> 'permitted') IS NOT NULL DESC"
}
{ setting: "after_signup", order: "(value::json ->> 'permitted') IS NOT NULL DESC" },
)
wizards.any? ? wizards.first : false
end
def self.prompt_completion(user)
wizards = list(
wizards =
list(
user,
{
setting: 'prompt_completion',
order: "(value::json ->> 'permitted') IS NOT NULL DESC"
},
true
{ setting: "prompt_completion", order: "(value::json ->> 'permitted') IS NOT NULL DESC" },
true,
)
if wizards.any?
wizards.map do |w|
{
id: w.id,
name: w.name
}
end
wizards.map { |w| { id: w.id, name: w.name } }
else
false
end
@ -389,7 +376,7 @@ class CustomWizard::Wizard
wizard = self.create(wizard_id, user)
if wizard.can_access?(always_allow_admin: false)
user.custom_fields['redirect_to_wizard'] = wizard_id
user.custom_fields["redirect_to_wizard"] = wizard_id
user.save_custom_fields(true)
else
false

Datei anzeigen

@ -13,7 +13,7 @@ module DiscoursePluginStatistics
step: {
required_data: 0,
permitted_params: 0,
force_final: 0
force_final: 0,
},
field: {
condition: 0,
@ -37,7 +37,7 @@ module DiscoursePluginStatistics
group: 0,
user_selector: 0,
},
realtime_validations: 0
realtime_validations: 0,
},
action: {
type: {
@ -52,12 +52,13 @@ module DiscoursePluginStatistics
add_to_group: 0,
create_group: 0,
create_category: 0,
}
}
},
},
}
increment_feature_count = lambda do |type, key, value|
if key == 'type'
increment_feature_count =
lambda do |type, key, value|
if key == "type"
if !subscription_features[type.to_sym][:type][value.to_sym].nil?
subscription_features[type.to_sym][:type][value.to_sym] += 1
end
@ -69,30 +70,22 @@ module DiscoursePluginStatistics
end
CustomWizard::Template.list.each do |template|
template.each do |key, value|
increment_feature_count.call(:wizard, key, value)
end
template['steps'].each do |step|
step.each do |key, value|
increment_feature_count.call(:step, key, value)
end
step['fields'].each do |field|
field.each do |key, value|
increment_feature_count.call(:field, key, value)
template.each { |key, value| increment_feature_count.call(:wizard, key, value) }
template["steps"].each do |step|
step.each { |key, value| increment_feature_count.call(:step, key, value) }
step["fields"].each do |field|
field.each { |key, value| increment_feature_count.call(:field, key, value) }
end
end
end
template['actions'].each do |action|
action.each do |key, value|
increment_feature_count.call(:action, key, value)
end
template["actions"].each do |action|
action.each { |key, value| increment_feature_count.call(:action, key, value) }
end
end
{
total_wizards: CustomWizard::Template.list.size,
subscription_type: CustomWizard::Subscription.type.to_s,
subscription_features: subscription_features
subscription_features: subscription_features,
}
end
end

Datei anzeigen

@ -1,19 +1,19 @@
# frozen_string_literal: true
# name: discourse-custom-wizard
# about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more.
# version: 2.8.11
# version: 2.8.12
# authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever, Juan Marcos Gutierrez Ramos
# url: https://github.com/paviliondev/discourse-custom-wizard
# contact_emails: development@pavilion.tech
# subscription_url: https://coop.pavilion.tech
# meta_topic_id: 73345
gem 'liquid', '5.5.0', require: true
gem "liquid", "5.5.0", require: true
gem "discourse_subscription_client", "0.1.6", require_name: "discourse_subscription_client"
gem 'discourse_plugin_statistics', '0.1.0.pre7', require: true
register_asset 'stylesheets/common/admin.scss'
register_asset 'stylesheets/common/wizard.scss'
register_svg_icon 'pavilion-logo'
gem "discourse_plugin_statistics", "0.1.0.pre7", require: true
register_asset "stylesheets/common/admin.scss"
register_asset "stylesheets/common/wizard.scss"
register_svg_icon "pavilion-logo"
register_svg_icon "hat-wizard"
enabled_site_setting :custom_wizard_enabled
@ -102,24 +102,18 @@ after_initialize do
../lib/custom_wizard/extensions/custom_field/serializer.rb
../lib/custom_wizard/extensions/custom_field/extension.rb
../lib/custom_wizard/extensions/discourse_tagging.rb
].each do |path|
load File.expand_path(path, __FILE__)
end
].each { |path| load File.expand_path(path, __FILE__) }
Liquid::Template.error_mode = :strict
# preloaded category custom fields
%w[
create_topic_wizard
].each do |custom_field|
%w[create_topic_wizard].each do |custom_field|
Site.preloaded_category_custom_fields << custom_field
end
Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty)
add_to_class(:topic, :wizard_submission_id) do
custom_fields['wizard_submission_id']
end
add_to_class(:topic, :wizard_submission_id) { custom_fields["wizard_submission_id"] }
add_class_method(:wizard, :user_requires_completion?) do |user|
wizard_result = self.new(user).requires_completion?
@ -127,10 +121,7 @@ after_initialize do
custom_redirect = false
if user &&
user.first_seen_at.blank? &&
wizard = CustomWizard::Wizard.after_signup(user)
if user && user.first_seen_at.blank? && wizard = CustomWizard::Wizard.after_signup(user)
if !wizard.completed?
custom_redirect = true
CustomWizard::Wizard.set_user_redirect(wizard.id, user)
@ -141,8 +132,8 @@ after_initialize do
end
add_to_class(:user, :redirect_to_wizard) do
if custom_fields['redirect_to_wizard'].present?
custom_fields['redirect_to_wizard']
if custom_fields["redirect_to_wizard"].present?
custom_fields["redirect_to_wizard"]
else
nil
end
@ -156,9 +147,7 @@ after_initialize do
end
end
add_to_serializer(:current_user, :redirect_to_wizard) do
object.redirect_to_wizard
end
add_to_serializer(:current_user, :redirect_to_wizard) { object.redirect_to_wizard }
on(:user_approved) do |user|
if wizard = CustomWizard::Wizard.after_signup(user)
@ -167,16 +156,16 @@ after_initialize do
end
add_to_class(:application_controller, :redirect_to_wizard_if_required) do
@excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split('|') + ['/w/']
@excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split("|") + ["/w/"]
url = request.referer || request.original_url
excluded_route = @excluded_routes.any? { |str| /#{str}/ =~ url }
not_api = request.format === 'text/html'
not_api = request.format === "text/html"
if not_api && !excluded_route
wizard_id = current_user.redirect_to_wizard
if CustomWizard::Template.can_redirect_users?(wizard_id)
if url !~ /\/w\// && url !~ /\/invites\//
if url !~ %r{/w/} && url !~ %r{/invites/}
CustomWizard::Wizard.set_wizard_redirect(current_user, wizard_id, url)
end
@ -209,9 +198,10 @@ after_initialize do
::UsersController.prepend CustomWizardUsersController
::Guardian.prepend CustomWizardGuardian
full_path = "#{Rails.root}/plugins/discourse-custom-wizard/assets/stylesheets/wizard/wizard_custom.scss"
full_path =
"#{Rails.root}/plugins/discourse-custom-wizard/assets/stylesheets/wizard/wizard_custom.scss"
if Stylesheet::Importer.respond_to?(:plugin_assets)
Stylesheet::Importer.plugin_assets['wizard_custom'] = Set[full_path]
Stylesheet::Importer.plugin_assets["wizard_custom"] = Set[full_path]
else
# legacy method, Discourse 2.7.0.beta5 and below
DiscoursePluginRegistry.register_asset(full_path, {}, "wizard_custom")
@ -225,7 +215,9 @@ after_initialize do
add_model_callback(klass, :after_initialize) do
if CustomWizard::CustomField.enabled?
CustomWizard::CustomField.list_by(:klass, klass.to_s).each do |field|
CustomWizard::CustomField
.list_by(:klass, klass.to_s)
.each do |field|
class_constant.register_custom_field_type(field[:name], field[:type].to_sym)
end
end
@ -247,10 +239,10 @@ after_initialize do
on(:before_create_topic) do |topic_params, user|
category = topic_params.category
wizard_submission_id = topic_params.custom_fields&.[]('wizard_submission_id')
if category&.custom_fields&.[]('create_topic_wizard').present? && wizard_submission_id.blank?
wizard_submission_id = topic_params.custom_fields&.[]("wizard_submission_id")
if category&.custom_fields&.[]("create_topic_wizard").present? && wizard_submission_id.blank?
raise Discourse::InvalidParameters.new(
I18n.t('wizard.error_messages.wizard_replacing_composer')
I18n.t("wizard.error_messages.wizard_replacing_composer"),
)
end
end

Datei anzeigen

@ -1,10 +1,26 @@
# frozen_string_literal: true
describe CustomWizard::Action do
fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) }
fab!(:user1) { Fabricate(:user, name: "Angus One", username: 'angus1', email: "angus_one@email.com", trust_level: TrustLevel[2]) }
fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') }
fab!(:tag) { Fabricate(:tag, name: 'tag1') }
fab!(:user) do
Fabricate(
:user,
name: "Angus",
username: "angus",
email: "angus@email.com",
trust_level: TrustLevel[2],
)
end
fab!(:user1) do
Fabricate(
:user,
name: "Angus One",
username: "angus1",
email: "angus_one@email.com",
trust_level: TrustLevel[2],
)
end
fab!(:category) { Fabricate(:category, name: "cat1", slug: "cat-slug") }
fab!(:tag) { Fabricate(:tag, name: "tag1") }
fab!(:group)
let(:wizard_template) { get_wizard_fixture("wizard") }
@ -24,103 +40,94 @@ describe CustomWizard::Action do
def update_template(template)
CustomWizard::Template.save(template, skip_jobs: true)
@template = CustomWizard::Template.find('super_mega_fun_wizard')
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
let(:create_topic) {
let(:create_topic) do
JSON.parse(
File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/actions/create_topic.json"
).read
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/actions/create_topic.json",
).read,
)
}
end
let(:custom_field_json) {
JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json"
).read)
}
let(:custom_field_json) do
JSON.parse(
File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json",
).read,
)
end
before do
Group.refresh_automatic_group!(:trust_level_2)
update_template(wizard_template)
end
describe '#create_topic' do
describe "#create_topic" do
it "works" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(
wizard.steps.first.id,
step_1_field_1: "Topic Title",
step_1_field_2: "topic body"
step_1_field_2: "topic body",
).update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(
title: "Topic Title",
category_id: category.id
)
topic = Topic.where(title: "Topic Title", category_id: category.id)
expect(topic.exists?).to eq(true)
expect(Post.where(
topic_id: topic.pluck(:id),
raw: "topic body"
).exists?).to eq(true)
expect(Post.where(topic_id: topic.pluck(:id), 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(
wizard.steps.first.id,
step_1_field_2: "topic body"
).update
wizard.create_updater(wizard.steps.first.id, step_1_field_2: "topic body").update
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(CustomWizard::UserHistory.where(
expect(
CustomWizard::UserHistory.where(
actor_id: user.id,
context: "super_mega_fun_wizard",
subject: "step_3"
).exists?).to eq(true)
expect(Post.where(
raw: "topic body"
).exists?).to eq(false)
subject: "step_3",
).exists?,
).to eq(true)
expect(Post.where(raw: "topic body").exists?).to eq(false)
end
it "adds custom fields" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(wizard.steps.first.id,
wizard.create_updater(
wizard.steps.first.id,
step_1_field_1: "Topic Title",
step_1_field_2: "topic body"
step_1_field_2: "topic body",
).update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(
title: "Topic Title",
category_id: category.id
).first
topic_custom_field = TopicCustomField.where(
topic = Topic.where(title: "Topic Title", category_id: category.id).first
topic_custom_field =
TopicCustomField.where(
name: "topic_field",
value: "Topic custom field value",
topic_id: topic.id
topic_id: topic.id,
)
topic_json_custom_field = TopicCustomField.where("
topic_json_custom_field =
TopicCustomField.where(
"
name = 'topic_json_field' AND
(value::json->>'key_1') = 'Key 1 value' AND
(value::json->>'key_2') = 'Key 2 value' AND
topic_id = #{topic.id}"
topic_id = #{topic.id}",
)
post_custom_field = PostCustomField.where(
post_custom_field =
PostCustomField.where(
name: "post_field",
value: "Post custom field value",
post_id: topic.first_post.id
post_id: topic.first_post.id,
)
expect(topic_custom_field.exists?).to eq(true)
expect(topic_json_custom_field.exists?).to eq(true)
@ -128,32 +135,33 @@ describe CustomWizard::Action do
end
it "adds registered custom fields" do
custom_field = custom_field_json['custom_fields'][0]
custom_field = custom_field_json["custom_fields"][0]
custom_field_name = custom_field["name"]
custom_field_value = "Custom value"
CustomWizard::CustomField.new(nil, custom_field).save
create_topic["custom_fields"] = [
{
"type": "association",
"pairs": [
type: "association",
pairs: [
{
"index": 0,
"key": custom_field_name,
"key_type": "custom_field",
"value": custom_field_value,
"value_type": "text",
"connector": "association"
}
]
}
index: 0,
key: custom_field_name,
key_type: "custom_field",
value: custom_field_value,
value_type: "text",
connector: "association",
},
],
},
]
wizard = CustomWizard::Wizard.new(@template, user)
action = CustomWizard::Action.new(
action =
CustomWizard::Action.new(
wizard: wizard,
action: create_topic.with_indifferent_access,
submission: wizard.current_submission
submission: wizard.current_submission,
)
action.perform
@ -163,14 +171,7 @@ describe CustomWizard::Action do
it "allows poster to be set" do
wizard_template[:actions][0]["poster"] = [
{
"type": "assignment",
"output_type": "user",
"output_connector": "set",
"output": [
"angus1"
]
}
{ type: "assignment", output_type: "user", output_connector: "set", output: ["angus1"] },
]
update_template(wizard_template)
@ -178,45 +179,39 @@ describe CustomWizard::Action do
wizard.create_updater(
wizard.steps.first.id,
step_1_field_1: "Topic Title",
step_1_field_2: "topic body"
step_1_field_2: "topic body",
).update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(
title: "Topic Title",
category_id: category.id
)
topic = Topic.where(title: "Topic Title", category_id: category.id)
expect(topic.exists?).to eq(true)
post = Post.find_by(
topic_id: topic.pluck(:id),
raw: "topic body"
)
post = Post.find_by(topic_id: topic.pluck(:id), raw: "topic body")
expect(post.present?).to eq(true)
expect(post.user.username).to eq('angus1')
expect(post.user.username).to eq("angus1")
end
end
it 'updates a profile' do
it "updates a profile" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
upload = Upload.create!(
url: '/images/image.png',
original_filename: 'image.png',
upload =
Upload.create!(
url: "/images/image.png",
original_filename: "image.png",
filesize: 100,
user_id: -1,
)
steps = wizard.steps
wizard.create_updater(steps[0].id, {}).update
wizard.create_updater(steps[1].id,
step_2_field_7: upload.as_json(only: [:id, :url, :user_id])
wizard.create_updater(
steps[1].id,
step_2_field_7: upload.as_json(only: %i[id url user_id]),
).update
expect(user.profile_background_upload.id).to eq(upload.id)
end
context "open composer" do
it 'works' 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
@ -224,19 +219,20 @@ describe CustomWizard::Action do
updater.update
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&tags=tag1"
"/new-topic?title=Title%20of%20the%20composer%20topic&body=I%20am%20interpolating%20some%20user%20fields%20Angus%20angus%20angus%40email.com&tags=tag1",
)
end
it 'encodes special characters in the title and body' do
open_composer['title'][0]['output'] = "Title that's special $".dup
open_composer['post_template'] = "Body & more body & more body".dup
it "encodes special characters in the title and body" do
open_composer["title"][0]["output"] = "Title that's special $".dup
open_composer["post_template"] = "Body & more body & more body".dup
wizard = CustomWizard::Wizard.new(@template, user)
action = CustomWizard::Action.new(
action =
CustomWizard::Action.new(
wizard: wizard,
action: open_composer,
submission: wizard.current_submission
submission: wizard.current_submission,
)
action.perform
@ -244,13 +240,13 @@ describe CustomWizard::Action do
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")
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
context "route to action" do
it 're-routes a user' do
it "re-routes a user" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
updater = wizard.create_updater(wizard.steps.last.id, {})
updater.update
@ -274,7 +270,7 @@ describe CustomWizard::Action do
Jobs.run_immediately!
end
it 'watches tags' do
it "watches tags" do
watch_tags[:tags][0][:output] = tag.name
wizard_template[:actions] << watch_tags
update_template(wizard_template)
@ -282,13 +278,10 @@ describe CustomWizard::Action do
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
expect(TagUser.where(
tag_id: tag.id,
user_id: user.id
).first.notification_level).to eq(2)
expect(TagUser.where(tag_id: tag.id, user_id: user.id).first.notification_level).to eq(2)
end
it 'watches categories' do
it "watches categories" do
watch_categories[:categories][0][:output] = category.id
wizard_template[:actions] << watch_categories
update_template(wizard_template)
@ -296,34 +289,27 @@ describe CustomWizard::Action do
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
expect(CategoryUser.where(
category_id: category.id,
user_id: user.id
).first.notification_level).to eq(2)
expect(
CategoryUser.where(category_id: category.id, user_id: user.id).first.notification_level,
).to eq(2)
end
it '#send_message' do
it "#send_message" do
Jobs.run_immediately!
target_user = Fabricate(:user)
send_message['recipient'][0]['output'][0] = target_user.username
wizard_template['actions'] << send_message
send_message["recipient"][0]["output"][0] = target_user.username
wizard_template["actions"] << send_message
update_template(wizard_template)
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"
)
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"
)
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(target_user.username)
@ -331,7 +317,7 @@ describe CustomWizard::Action do
expect(target_user.reload.notifications.count).to eq(1)
end
it '#send_message allows using multiple targets' do
it "#send_message allows using multiple targets" do
Jobs.run_immediately!
user1 = Fabricate(:user)
@ -339,13 +325,13 @@ describe CustomWizard::Action do
group1 = Fabricate(:group)
group2 = Fabricate(:group)
send_message_multi['recipient'][0]['output'] = [
send_message_multi["recipient"][0]["output"] = [
user1.username,
user2.username,
group1.name,
group2.name
group2.name,
]
wizard_template['actions'] << send_message_multi
wizard_template["actions"] << send_message_multi
update_template(wizard_template)
update_template(wizard_template)
@ -353,18 +339,15 @@ describe CustomWizard::Action do
wizard.create_updater(wizard.steps[0].id, {}).update
wizard.create_updater(wizard.steps[1].id, {}).update
topic = Topic.where(
archetype: Archetype.private_message,
title: "Multiple Recipients title"
)
topic = Topic.where(archetype: Archetype.private_message, title: "Multiple Recipients title")
post = Post.where(
topic_id: topic.pluck(:id),
raw: "I will interpolate some wizard fields"
)
post = Post.where(topic_id: topic.pluck(:id), raw: "I will interpolate some wizard fields")
expect(topic.exists?).to eq(true)
expect(topic.first.all_allowed_users.map(&:username)).to include(user1.username, user2.username)
expect(topic.first.all_allowed_users.map(&:username)).to include(
user1.username,
user2.username,
)
expect(topic.first.allowed_groups.map(&:name)).to include(group1.name, group2.name)
expect(post.exists?).to eq(true)
expect(user1.reload.notifications.count).to eq(1)
@ -378,27 +361,27 @@ describe CustomWizard::Action do
wizard_template["permitted"] = guests_permitted["permitted"]
wizard_template[:steps][0][:fields] << {
"id": "step_1_field_5",
"label": "Guest Email",
"type": "text",
"min_length": "3",
id: "step_1_field_5",
label: "Guest Email",
type: "text",
min_length: "3",
}.as_json
create_topic["run_after"] = "step_3"
create_topic["guest_email"] = [
{
"type": "assignment",
"output": "step_1_field_5",
"output_type": "wizard_field",
"output_connector": "set"
}
type: "assignment",
output: "step_1_field_5",
output_type: "wizard_field",
output_connector: "set",
},
]
create_topic["category"] = [
{
"type": "assignment",
"output": "step_3_field_3",
"output_type": "wizard_field",
"output_connector": "set"
}
type: "assignment",
output: "step_3_field_3",
output_type: "wizard_field",
output_connector: "set",
},
]
wizard_template.delete("actions")
wizard_template[:actions] = [create_topic]
@ -407,47 +390,39 @@ describe CustomWizard::Action do
end
it "creates a staged guest poster if guest_email is set" do
wizard = CustomWizard::Builder.new(
wizard =
CustomWizard::Builder.new(
@template[:id],
nil,
CustomWizard::Wizard.generate_guest_id
CustomWizard::Wizard.generate_guest_id,
).build
wizard.create_updater(
wizard.steps.first.id,
step_1_field_5: "guest@email.com"
).update
wizard.create_updater(wizard.steps.first.id, step_1_field_5: "guest@email.com").update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(category_id: category.id).first
expect(topic.present?).to eq(true)
expect(topic.posts.first.user.staged).to eq(true)
expect(topic.posts.first.user.primary_email.email).to eq('guest@email.com')
expect(topic.posts.first.user.primary_email.email).to eq("guest@email.com")
end
it "returns an existing user with the same email" do
existing = Fabricate(:user, email: 'guest@email.com')
existing = Fabricate(:user, email: "guest@email.com")
wizard = CustomWizard::Builder.new(
wizard =
CustomWizard::Builder.new(
@template[:id],
nil,
CustomWizard::Wizard.generate_guest_id
CustomWizard::Wizard.generate_guest_id,
).build
wizard.create_updater(
wizard.steps.first.id,
step_1_field_5: "guest@email.com"
).update
wizard.create_updater(wizard.steps.first.id, step_1_field_5: "guest@email.com").update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(category_id: category.id).first
expect(topic.present?).to eq(true)
expect(topic.posts.first.user.staged).to eq(false)
expect(topic.posts.first.user.primary_email.email).to eq('guest@email.com')
expect(topic.posts.first.user.primary_email.email).to eq("guest@email.com")
end
end
@ -455,10 +430,15 @@ describe CustomWizard::Action do
it "works" do
wizard_template["permitted"] = guests_permitted["permitted"]
wizard_template.delete("actions")
wizard_template['actions'] = [send_message]
wizard_template["actions"] = [send_message]
update_template(wizard_template)
wizard = CustomWizard::Builder.new(wizard_template["id"], nil, CustomWizard::Wizard.generate_guest_id).build
wizard =
CustomWizard::Builder.new(
wizard_template["id"],
nil,
CustomWizard::Wizard.generate_guest_id,
).build
wizard.create_updater(wizard.steps[0].id, {}).update
updater = wizard.create_updater(wizard.steps[1].id, {})
updater.update
@ -468,7 +448,9 @@ describe CustomWizard::Action do
expect(topic.exists?).to eq(true)
expect(topic.first.topic_allowed_users.first.user.username).to eq(user1.username)
expect(topic.first.topic_allowed_users.second.user.username).to eq(Discourse.system_user.username)
expect(topic.first.topic_allowed_users.second.user.username).to eq(
Discourse.system_user.username,
)
expect(post.exists?).to eq(true)
end
@ -480,19 +462,24 @@ describe CustomWizard::Action do
send_message["recipient"] = [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
type: "assignment",
output: "step_1_field_1",
output_type: "wizard_field",
output_connector: "set",
},
]
wizard_template['actions'] = [send_message]
wizard_template["actions"] = [send_message]
update_template(wizard_template)
NotificationEmailer.expects(:process_notification).once
wizard = CustomWizard::Builder.new(wizard_template["id"], nil, CustomWizard::Wizard.generate_guest_id).build
wizard =
CustomWizard::Builder.new(
wizard_template["id"],
nil,
CustomWizard::Wizard.generate_guest_id,
).build
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "guest@email.com").update
updater = wizard.create_updater(wizard.steps[1].id, {})
updater.update
@ -502,8 +489,12 @@ describe CustomWizard::Action do
expect(topic.exists?).to eq(true)
expect(topic.first.topic_allowed_users.first.user.staged).to eq(true)
expect(topic.first.topic_allowed_users.first.user.primary_email.email).to eq('guest@email.com')
expect(topic.first.topic_allowed_users.second.user.username).to eq(Discourse.system_user.username)
expect(topic.first.topic_allowed_users.first.user.primary_email.email).to eq(
"guest@email.com",
)
expect(topic.first.topic_allowed_users.second.user.username).to eq(
Discourse.system_user.username,
)
expect(post.exists?).to eq(true)
end
end
@ -511,71 +502,71 @@ describe CustomWizard::Action do
end
context "business subscription actions" do
before do
enable_subscription("business")
end
before { enable_subscription("business") }
it '#create_category' do
wizard_template['actions'] << create_category
wizard_template['actions'] << create_group
it "#create_category" do
wizard_template["actions"] << create_category
wizard_template["actions"] << create_group
update_template(wizard_template)
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.fields['action_8']).exists?).to eq(true)
expect(Category.where(id: wizard.current_submission.fields["action_8"]).exists?).to eq(true)
end
it '#create_group' do
wizard_template['actions'] << create_group
it "#create_group" do
wizard_template["actions"] << create_group
update_template(wizard_template)
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
group_id = Group.where(name: wizard.current_submission.fields['action_9']).first.id
user_id = User.find_by(username: wizard_template['actions'][4]['usernames'][0]["output"][0]).id
group_id = Group.where(name: wizard.current_submission.fields["action_9"]).first.id
user_id =
User.find_by(username: wizard_template["actions"][4]["usernames"][0]["output"][0]).id
expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true)
expect(Group.where(name: wizard.current_submission.fields["action_9"]).exists?).to eq(true)
expect(GroupUser.where(group_id: group_id, user_id: user_id).exists?).to eq(true)
end
it '#create_group completes successfully when user included in usernames does not exist but excludes users who do not exist and includes warning in log' do
wizard_template['actions'] << create_group_with_nonexistent_user
it "#create_group completes successfully when user included in usernames does not exist but excludes users who do not exist and includes warning in log" do
wizard_template["actions"] << create_group_with_nonexistent_user
update_template(wizard_template)
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
group_id = Group.where(name: wizard.current_submission.fields['action_9']).first.id
group_id = Group.where(name: wizard.current_submission.fields["action_9"]).first.id
expect(CustomWizard::Log.list_query.all.last.value.include? "some users were not found").to eq(true)
expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true)
expect(
CustomWizard::Log.list_query.all.last.value.include? "some users were not found"
).to eq(true)
expect(Group.where(name: wizard.current_submission.fields["action_9"]).exists?).to eq(true)
expect(GroupUser.where(group_id: group_id).count).to eq(1)
end
it '#add_to_group' do
wizard_template['actions'] << create_group
wizard_template['actions'] << add_to_group
it "#add_to_group" do
wizard_template["actions"] << create_group
wizard_template["actions"] << add_to_group
update_template(wizard_template)
wizard = CustomWizard::Builder.new(@template[:id], user).build
step_id = wizard.steps[0].id
updater = wizard.create_updater(step_id, step_1_field_1: "Text input").update
group = Group.find_by(name: wizard.current_submission.fields['action_9'])
group = Group.find_by(name: wizard.current_submission.fields["action_9"])
expect(group.users.first.username).to eq('angus')
expect(group.users.first.username).to eq("angus")
end
it '#send_to_api successful' do
stub_request(:put, "https://myexternalapi.com/update").
with(
it "#send_to_api successful" do
stub_request(:put, "https://myexternalapi.com/update").with(
body: "some_body",
headers: {
'Host' => 'myexternalapi.com'
}).
to_return(status: 200, body: "success", headers: {})
"Host" => "myexternalapi.com",
},
).to_return(status: 200, body: "success", headers: {})
new_api = CustomWizard::Api.new("my_api")
CustomWizard::Api.set("my_api", title: "Mocked external api")
@ -587,18 +578,17 @@ describe CustomWizard::Action do
result = CustomWizard::Api::Endpoint.request("my_api", endpoint_id, "some_body")
log_entry = CustomWizard::Api::LogEntry.list("my_api").first
expect(result).to eq('success')
expect(log_entry.status).to eq('SUCCESS')
expect(result).to eq("success")
expect(log_entry.status).to eq("SUCCESS")
end
it '#send_to_api failure' do
stub_request(:put, "https://myexternalapi.com/update").
with(
it "#send_to_api failure" do
stub_request(:put, "https://myexternalapi.com/update").with(
body: "some_body",
headers: {
'Host' => 'myexternalapi.com'
}).
to_return(status: 500, body: "failure", headers: {})
"Host" => "myexternalapi.com",
},
).to_return(status: 500, body: "failure", headers: {})
new_api = CustomWizard::Api.new("my_api")
CustomWizard::Api.set("my_api", title: "Mocked external api")
@ -611,21 +601,22 @@ describe CustomWizard::Action do
log_entry = CustomWizard::Api::LogEntry.list("my_api").first
expect(result).to eq({ error: "API request failed" })
expect(log_entry.status).to eq('FAIL')
expect(log_entry.status).to eq("FAIL")
end
end
it 'registers callbacks' do
it "registers callbacks" do
described_class.register_callback(:before_create_topic) do |params, wizard, action, submission|
params[:topic_opts][:custom_fields]["topic_custom_field"] = true
params
end
wizard = CustomWizard::Builder.new(@template[:id], user).build
action = CustomWizard::Action.new(
action =
CustomWizard::Action.new(
wizard: wizard,
action: create_topic.with_indifferent_access,
submission: wizard.current_submission
submission: wizard.current_submission,
)
action.perform
@ -633,27 +624,24 @@ describe CustomWizard::Action do
expect(Topic.find(action.result.output).custom_fields["topic_custom_field"]).to eq("t")
end
context 'creating a topic when there are multiple actions' do
it 'works' do
wizard_template['actions'] << create_topic
wizard_template['actions'] << send_message
context "creating a topic when there are multiple actions" do
it "works" do
wizard_template["actions"] << create_topic
wizard_template["actions"] << send_message
update_template(wizard_template)
wizard = CustomWizard::Builder.new(@template[:id], user).build
wizard.create_updater(
wizard.steps.first.id,
step_1_field_1: 'Topic Title',
step_1_field_2: 'topic body'
step_1_field_1: "Topic Title",
step_1_field_2: "topic body",
).update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id)
.update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
wizard.create_updater(wizard.steps[0].id, {}).update
wizard.create_updater(wizard.steps[1].id, {}).update
topic = Topic.where(title: 'Topic Title', category_id: category.id)
topic = Topic.where(title: "Topic Title", category_id: category.id)
expect(topic.exists?).to eq(true)
expect(
Post.where(topic_id: topic.pluck(:id), raw: 'topic body').exists?
).to eq(true)
expect(Post.where(topic_id: topic.pluck(:id), raw: "topic body").exists?).to eq(true)
end
end
end

Datei anzeigen

@ -1,18 +1,13 @@
# frozen_string_literal: true
describe CustomWizard::Builder do
fab!(:trusted_user) {
Fabricate(
:user,
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) }
fab!(:trusted_user) do
Fabricate(:user, username: "angus", email: "angus@email.com", trust_level: TrustLevel[3])
end
fab!(:user)
fab!(:category1) { Fabricate(:category, name: "cat1") }
fab!(:category2) { Fabricate(:category, name: "cat2") }
fab!(:group)
let(:wizard_template) { get_wizard_fixture("wizard") }
let(:required_data_json) { get_wizard_fixture("step/required_data") }
@ -20,36 +15,30 @@ describe CustomWizard::Builder do
let(:permitted_param_json) { get_wizard_fixture("step/permitted_params") }
let(:user_condition_json) { get_wizard_fixture("condition/user_condition") }
let(:boolean_field_condition_json) {
let(:boolean_field_condition_json) do
JSON.parse(
File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/condition/boolean_field_condition.json"
).read
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/condition/boolean_field_condition.json",
).read,
)
}
end
before do
Group.refresh_automatic_group!(:trust_level_3)
CustomWizard::Template.save(wizard_template, skip_jobs: true)
@template = CustomWizard::Template.find('super_mega_fun_wizard')
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
context 'disabled' do
before do
SiteSetting.custom_wizard_enabled = false
end
context "disabled" do
before { SiteSetting.custom_wizard_enabled = false }
it "returns nil" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
).to eq(nil)
expect(CustomWizard::Builder.new(@template[:id], user).build).to eq(nil)
end
end
context 'enabled' do
before do
SiteSetting.custom_wizard_enabled = true
end
context "enabled" do
before { SiteSetting.custom_wizard_enabled = true }
it "returns wizard metadata" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
@ -59,10 +48,7 @@ describe CustomWizard::Builder do
end
it "returns steps" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.length
).to eq(3)
expect(CustomWizard::Builder.new(@template[:id], user).build.steps.length).to eq(3)
end
context "with multiple submissions disabled" do
@ -71,27 +57,21 @@ describe CustomWizard::Builder do
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)
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
it "returns no steps if user has completed it" do
@template[:steps].each do |step|
CustomWizard::UserHistory.create!(
action: CustomWizard::UserHistory.actions[:step],
actor_id: user.id,
context: @template[:id],
subject: step[:id]
subject: step[:id],
)
end
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.length
).to eq(0)
expect(CustomWizard::Builder.new(@template[:id], user).build.steps.length).to eq(0)
end
end
@ -102,81 +82,56 @@ describe CustomWizard::Builder do
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)
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)
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")
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)
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)
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)
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
.steps.length
).to eq(3)
it "returns steps if user is permitted" do
expect(CustomWizard::Builder.new(@template[:id], trusted_user).build.steps.length).to eq(3)
end
end
it 'returns prefilled data' do
it "returns prefilled data" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.first
.fields.first
.value
).to eq('I am prefilled')
CustomWizard::Builder.new(@template[:id], user).build.steps.first.fields.first.value,
).to eq("I am prefilled")
end
context "user has partially completed" do
before do
wizard = CustomWizard::Wizard.new(@template, user)
data = {
step_1_field_1: 'I am a user submission'
}
data = { step_1_field_1: "I am a user submission" }
CustomWizard::Submission.new(wizard, data).save
end
it 'returns saved submissions' do
it "returns saved submissions" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.first
.fields.first
.value
).to eq('I am a user submission')
CustomWizard::Builder.new(@template[:id], user).build.steps.first.fields.first.value,
).to eq("I am a user submission")
end
context "restart is enabled" do
@ -186,100 +141,87 @@ describe CustomWizard::Builder do
CustomWizard::Template.save(@template.as_json)
end
it 'does not return saved submissions' do
it "does not return saved submissions" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.first
.fields.first
.value
).to eq('I am prefilled')
CustomWizard::Builder.new(@template[:id], user).build.steps.first.fields.first.value,
).to eq("I am prefilled")
end
end
end
context 'building step' do
it 'returns step metadata' do
first_step = CustomWizard::Builder.new(@template[:id], user)
.build(reset: true)
.steps.first
context "building step" do
it "returns step metadata" 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
context "with required data" do
before do
enable_subscription("standard")
@template[:steps][0][:required_data] = required_data_json['required_data']
@template[:steps][0][:required_data_message] = required_data_json['required_data_message']
@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
.steps.first
.permitted
).to eq(false)
it "is not permitted if required data is not present" do
expect(CustomWizard::Builder.new(@template[:id], user).build.steps.first.permitted).to eq(
false,
)
end
it 'it shows required data message' do
it "it shows required data message" do
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.first
.permitted_message
CustomWizard::Builder.new(@template[:id], user).build.steps.first.permitted_message,
).to eq("Missing required data")
end
it 'is permitted if required data is present' do
wizard = CustomWizard::Wizard.create('super_mega_fun_wizard', user)
it "is permitted if required data is present" do
wizard = CustomWizard::Wizard.create("super_mega_fun_wizard", user)
CustomWizard::Submission.new(wizard, step_1_field_1: "required").save
expect(
CustomWizard::Builder.new(@template[:id], user).build
.steps.first
.permitted
).to eq(true)
expect(CustomWizard::Builder.new(@template[:id], user).build.steps.first.permitted).to eq(
true,
)
end
end
context "with permitted params" do
before do
enable_subscription("standard")
@template[:steps][0][:permitted_params] = permitted_param_json['permitted_params']
@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.fields['saved_param']).to eq('param_value')
it "saves permitted params" do
wizard = CustomWizard::Builder.new(@template[:id], user).build({}, param: "param_value")
expect(wizard.current_submission.fields["saved_param"]).to eq("param_value")
end
end
context "with condition" do
before do
enable_subscription("standard")
@template[:steps][0][:condition] = user_condition_json['condition']
@template[:steps][0][:condition] = user_condition_json["condition"]
CustomWizard::Template.save(@template.as_json)
end
it "adds step when condition is passed" do
wizard = CustomWizard::Builder.new(@template[:id], trusted_user).build
expect(wizard.steps.first.id).to eq(@template[:steps][0]['id'])
expect(wizard.steps.first.id).to eq(@template[:steps][0]["id"])
end
it "does not add step when condition is not passed" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
expect(wizard.steps.first.id).to eq(@template[:steps][1]['id'])
expect(wizard.steps.first.id).to eq(@template[:steps][1]["id"])
end
end
end
context 'building field' do
it 'returns field metadata' do
context "building field" do
it "returns field metadata" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
field = wizard.steps.first.fields.first
@ -289,59 +231,56 @@ describe CustomWizard::Builder do
expect(field.min_length).to eq("3")
end
it 'returns all step fields' do
it "returns all step fields" do
expect(
CustomWizard::Builder.new(@template[:id], user)
.build
.steps.first
.fields.length
CustomWizard::Builder.new(@template[:id], user).build.steps.first.fields.length,
).to eq(@template[:steps][0][:fields].length)
end
context "with condition" do
before do
enable_subscription("standard")
@template[:steps][0][:fields][0][:condition] = user_condition_json['condition']
@template[:steps][2][:fields][0][:condition] = boolean_field_condition_json['condition']
@template[:steps][0][:fields][0][:condition] = user_condition_json["condition"]
@template[:steps][2][:fields][0][:condition] = boolean_field_condition_json["condition"]
CustomWizard::Template.save(@template.as_json)
end
it "adds field when condition is passed" do
wizard = CustomWizard::Builder.new(@template[:id], trusted_user).build
expect(wizard.steps.first.fields.first.id).to eq(@template[:steps][0][:fields][0]['id'])
expect(wizard.steps.first.fields.first.id).to eq(@template[:steps][0][:fields][0]["id"])
end
it "does not add field when condition is not passed" do
wizard = CustomWizard::Builder.new(@template[:id], user).build
expect(wizard.steps.first.fields.first.id).to eq(@template[:steps][0][:fields][1]['id'])
expect(wizard.steps.first.fields.first.id).to eq(@template[:steps][0][:fields][1]["id"])
end
it "works if a field condition uses 'is true/false'" do
builder = CustomWizard::Builder.new(@template[:id], user)
wizard = builder.build
wizard.create_updater('step_2', step_2_field_5: 'true').update
wizard.create_updater("step_2", step_2_field_5: "true").update
builder = CustomWizard::Builder.new(@template[:id], user)
wizard = builder.build
expect(wizard.steps.last.fields.last.id).to eq(@template[:steps][2][:fields][0]['id'])
expect(wizard.steps.last.fields.last.id).to eq(@template[:steps][2][:fields][0]["id"])
end
end
end
context 'on update' do
context "on update" do
def perform_update(step_id, submission)
updater = @wizard.create_updater(step_id, submission)
updater.update
updater
end
it 'saves submissions' do
it "saves submissions" do
@wizard = CustomWizard::Builder.new(@template[:id], user).build
perform_update('step_1', step_1_field_1: 'Text input')
expect(@wizard.current_submission.fields['step_1_field_1']).to eq('Text input')
perform_update("step_1", step_1_field_1: "Text input")
expect(@wizard.current_submission.fields["step_1_field_1"]).to eq("Text input")
end
context 'save submissions disabled' do
context "save submissions disabled" do
before do
enable_subscription("standard")
@template[:save_submissions] = false
@ -350,7 +289,7 @@ describe CustomWizard::Builder do
end
it "does not save submissions" do
perform_update('step_1', step_1_field_1: 'Text input')
perform_update("step_1", step_1_field_1: "Text input")
expect(@wizard.current_submission.present?).to eq(false)
end
end

Datei anzeigen

@ -2,22 +2,20 @@
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)
CustomWizard::Cache.new("list").delete
expect(CustomWizard::Cache.new("list").read).to eq(nil)
end
describe "#wrap" do
before do
@raw = [1, 2, 3]
end
before { @raw = [1, 2, 3] }
def list
CustomWizard::Cache.wrap('list') { @raw }
CustomWizard::Cache.wrap("list") { @raw }
end
it "returns value from passed block" do

Datei anzeigen

@ -2,224 +2,229 @@
describe CustomWizard::CustomField do
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
let(:custom_field_subscription_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
before do
CustomWizard::CustomField.invalidate_cache
let(:custom_field_subscription_json) do
get_wizard_fixture("custom_field/subscription_custom_fields")
end
before { CustomWizard::CustomField.invalidate_cache }
it "saves custom field records" do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
custom_field = CustomWizard::CustomField.new(nil, field_json)
expect(custom_field.save).to eq(true)
expect(
PluginStoreRow.where("
PluginStoreRow.where(
"
plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND
key = '#{custom_field.name}' AND
value::jsonb = '#{field_json.except('name').to_json}'::jsonb
",).exists?
value::jsonb = '#{field_json.except("name").to_json}'::jsonb
",
).exists?,
).to eq(true)
end
end
it "updates existing custom field records" do
custom_field_json['custom_fields'].each do |field_json|
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"]
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("
PluginStoreRow.where(
"
plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND
key = '#{updated_field.name}' AND
value::jsonb = '#{updated_field_json.except('name').to_json}'::jsonb
",).exists?
value::jsonb = '#{updated_field_json.except("name").to_json}'::jsonb
",
).exists?,
).to eq(true)
end
context "validation" do
it "does not save without required attributes" do
invalid_field_json = custom_field_json['custom_fields'].first
invalid_field_json['klass'] = nil
invalid_field_json = custom_field_json["custom_fields"].first
invalid_field_json["klass"] = nil
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(
I18n.t("wizard.custom_field.error.required_attribute", attr: "klass")
I18n.t("wizard.custom_field.error.required_attribute", attr: "klass"),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).exists?,
).to eq(false)
end
it "does save without optional attributes" do
field_json = custom_field_json['custom_fields'].first
field_json['serializers'] = nil
field_json = custom_field_json["custom_fields"].first
field_json["serializers"] = nil
custom_field = CustomWizard::CustomField.new(nil, field_json)
expect(custom_field.save).to eq(true)
expect(custom_field.valid?).to eq(true)
expect(
PluginStoreRow.where("
PluginStoreRow.where(
"
plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND
key = '#{custom_field.name}' AND
value::jsonb = '#{field_json.except('name').to_json}'::jsonb
",).exists?
value::jsonb = '#{field_json.except("name").to_json}'::jsonb
",
).exists?,
).to eq(true)
end
it "does not save with an unsupported class" do
invalid_field_json = custom_field_json['custom_fields'].first
invalid_field_json['klass'] = 'user'
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(
I18n.t("wizard.custom_field.error.unsupported_class", class: "user")
I18n.t("wizard.custom_field.error.unsupported_class", class: "user"),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).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'] = 'post'
invalid_field_json['serializers'] = ['post', 'post_revision']
invalid_field_json = custom_field_json["custom_fields"].first
invalid_field_json["klass"] = "post"
invalid_field_json["serializers"] = %w[post post_revision]
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(
I18n.t("wizard.custom_field.error.unsupported_serializers",
I18n.t(
"wizard.custom_field.error.unsupported_serializers",
class: "post",
serializers: "post_revision"
)
serializers: "post_revision",
),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).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'
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(
I18n.t("wizard.custom_field.error.unsupported_type", type: "bigint")
I18n.t("wizard.custom_field.error.unsupported_type", type: "bigint"),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).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'
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(
I18n.t("wizard.custom_field.error.name_too_short", name: "cf")
I18n.t("wizard.custom_field.error.name_too_short", name: "cf"),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).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|
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]
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")
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"]
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(
I18n.t("wizard.custom_field.error.name_invalid", name: ["invalid_name"])
I18n.t("wizard.custom_field.error.name_invalid", name: ["invalid_name"]),
)
expect(
PluginStoreRow.where(
plugin_name: CustomWizard::CustomField::NAMESPACE,
key: custom_field.name
).exists?
key: custom_field.name,
).exists?,
).to eq(false)
end
it "does not save subscription field types without a subscription" do
subscription_field_json = custom_field_subscription_json['custom_fields'].first
subscription_field_json = custom_field_subscription_json["custom_fields"].first
custom_field = CustomWizard::CustomField.new(nil, subscription_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.subscription_type", type: "json")
I18n.t("wizard.custom_field.error.subscription_type", type: "json"),
)
end
it "does not save subscription field classes without a subscription" do
subscription_field_json = custom_field_subscription_json['custom_fields'].second
subscription_field_json = custom_field_subscription_json["custom_fields"].second
custom_field = CustomWizard::CustomField.new(nil, subscription_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.subscription_type", type: "category")
I18n.t("wizard.custom_field.error.subscription_type", type: "category"),
)
end
context "with a subscription" do
before do
enable_subscription("business")
end
before { enable_subscription("business") }
it "saves subscription field types" do
subscription_field_json = custom_field_subscription_json['custom_fields'].first
subscription_field_json = custom_field_subscription_json["custom_fields"].first
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
expect(custom_field.save).to eq(true)
@ -227,7 +232,7 @@ describe CustomWizard::CustomField do
end
it "saves subscription field classes" do
subscription_field_json = custom_field_subscription_json['custom_fields'].second
subscription_field_json = custom_field_subscription_json["custom_fields"].second
custom_field = CustomWizard::CustomField.new(nil, subscription_field_json)
expect(custom_field.save).to eq(true)
@ -238,7 +243,7 @@ describe CustomWizard::CustomField do
context "lists" do
before do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
CustomWizard::CustomField.new(nil, field_json).save
end
end
@ -248,15 +253,15 @@ describe CustomWizard::CustomField do
end
it "saved custom field records by attribute value" do
expect(CustomWizard::CustomField.list_by(:klass, 'topic').length).to eq(1)
expect(CustomWizard::CustomField.list_by(:klass, "topic").length).to eq(1)
end
it "saved custom field records by optional values" do
field_json = custom_field_json['custom_fields'].first
field_json['serializers'] = nil
field_json = custom_field_json["custom_fields"].first
field_json["serializers"] = nil
custom_field = CustomWizard::CustomField.new(nil, field_json)
expect(CustomWizard::CustomField.list_by(:serializers, ['post']).length).to eq(0)
expect(CustomWizard::CustomField.list_by(:serializers, ["post"]).length).to eq(0)
end
it "custom field records added by other plugins " do
@ -269,7 +274,7 @@ describe CustomWizard::CustomField do
end
it "is enabled if there are custom fields" do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
CustomWizard::CustomField.new(nil, field_json).save
end
expect(CustomWizard::CustomField.enabled?).to eq(true)

Datei anzeigen

@ -5,12 +5,14 @@ describe CustomWizard::Field do
before do
CustomWizard::Field.register(
'location',
'discourse-locations',
['components', 'helpers', 'lib', 'stylesheets', 'templates'],
"location",
"discourse-locations",
%w[components helpers lib stylesheets templates],
type_opts: {
prefill: { "coordinates": [35.3082, 149.1244] }
}
prefill: {
coordinates: [35.3082, 149.1244],
},
},
)
end
@ -31,14 +33,14 @@ describe CustomWizard::Field do
end
it "allows custom field types to set default attributes" do
expect(
CustomWizard::Field.types[:location][:prefill]
).to eq({ "coordinates": [35.3082, 149.1244] })
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'])
expect(CustomWizard::Field.require_assets["discourse-locations"]).to eq(
%w[components helpers lib stylesheets templates],
)
end
end

Datei anzeigen

@ -2,32 +2,42 @@
describe CustomWizard::Log do
before do
CustomWizard::Log.create('first-test-wizard', 'perform_first_action', 'first_test_user', 'First log message', 5.minutes.ago)
CustomWizard::Log.create('second-test-wizard', 'perform_second_action', 'second_test_user', 'Second log message', 3.minutes.ago)
CustomWizard::Log.create('third-test-wizard', 'perform_third_action', 'third_test_user', 'Third log message', 1.minutes.ago)
CustomWizard::Log.create(
"first-test-wizard",
"perform_first_action",
"first_test_user",
"First log message",
5.minutes.ago,
)
CustomWizard::Log.create(
"second-test-wizard",
"perform_second_action",
"second_test_user",
"Second log message",
3.minutes.ago,
)
CustomWizard::Log.create(
"third-test-wizard",
"perform_third_action",
"third_test_user",
"Third log message",
1.minutes.ago,
)
end
it "creates logs" do
expect(
CustomWizard::Log.list.logs.length
).to eq(3)
expect(CustomWizard::Log.list.logs.length).to eq(3)
end
it "lists logs by time created" do
expect(
CustomWizard::Log.list.logs.first.message
).to eq("Third log message")
expect(CustomWizard::Log.list.logs.first.message).to eq("Third log message")
end
it "paginates logs" do
expect(
CustomWizard::Log.list(0, 2).logs.length
).to eq(2)
expect(CustomWizard::Log.list(0, 2).logs.length).to eq(2)
end
it "lists logs by wizard" do
expect(
CustomWizard::Log.list(0, 2, 'third-test-wizard').logs.length
).to eq(1)
expect(CustomWizard::Log.list(0, 2, "third-test-wizard").logs.length).to eq(1)
end
end

Datei anzeigen

@ -1,429 +1,403 @@
# rubocop:disable Style/FrozenStringLiteralComment
describe CustomWizard::Mapper do
fab!(:user1) {
Fabricate(:user,
fab!(:user1) do
Fabricate(
:user,
name: "Angus",
username: "angus",
email: "angus@email.com",
trust_level: TrustLevel[3]
trust_level: TrustLevel[3],
)
}
fab!(:user2) {
Fabricate(:user,
end
fab!(:user2) do
Fabricate(
:user,
name: "Patrick",
username: "patrick",
email: "patrick@email2.com",
trust_level: TrustLevel[1]
trust_level: TrustLevel[1],
)
}
fab!(:user_field) {
field = Fabricate(:user_field,
end
fab!(:user_field) do
field =
Fabricate(
:user_field,
id: 3,
name: 'dropdown_field',
description: 'field desc',
field_type: 'dropdown',
user_field_options_attributes: [
{ value: "a" },
{ value: "b" },
{ value: "c" }
]
name: "dropdown_field",
description: "field desc",
field_type: "dropdown",
user_field_options_attributes: [{ value: "a" }, { value: "b" }, { value: "c" }],
)
}
end
let(:inputs) { get_wizard_fixture("mapper/inputs") }
let(:data) { get_wizard_fixture("mapper/data") }
let(:template_params) {
{
"step_1_field_1" => "Hello"
}
}
let(:template_params_empty) {
{
"step_1_field_1" => nil,
"step_1_field_2" => nil,
"step_1_field_3" => ""
}
}
let(:template_params_non_empty) {
{
"step_1_field_1" => nil,
"step_1_field_2" => "",
"step_1_field_3" => "Value"
}
}
let(:template_params_multiple_non_empty) {
{
"step_1_field_1" => nil,
"step_1_field_2" => "Value1",
"step_1_field_3" => "Value"
}
}
let(:template_params_object) {
{
"step_1_field_1": get_wizard_fixture("field/upload")
}
}
let(:template_params_object_array) {
{
"step_1_field_1" => [{ text: "Hello" }, { text: "World" }]
}
}
let(:template_params) { { "step_1_field_1" => "Hello" } }
let(:template_params_empty) do
{ "step_1_field_1" => nil, "step_1_field_2" => nil, "step_1_field_3" => "" }
end
let(:template_params_non_empty) do
{ "step_1_field_1" => nil, "step_1_field_2" => "", "step_1_field_3" => "Value" }
end
let(:template_params_multiple_non_empty) do
{ "step_1_field_1" => nil, "step_1_field_2" => "Value1", "step_1_field_3" => "Value" }
end
let(:template_params_object) { { step_1_field_1: get_wizard_fixture("field/upload") } }
let(:template_params_object_array) do
{ "step_1_field_1" => [{ text: "Hello" }, { text: "World" }] }
end
def create_template_mapper(data, user)
CustomWizard::Mapper.new(
data: data,
user: user
)
CustomWizard::Mapper.new(data: data, user: user)
end
it "maps values" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment'],
data: data,
user: user1
).perform).to eq([13])
expect(
CustomWizard::Mapper.new(inputs: inputs["assignment"], data: data, user: user1).perform,
).to eq([13])
end
it "maps associations" do
association = CustomWizard::Mapper.new(
inputs: inputs['association'],
data: data,
user: user1
).perform
association =
CustomWizard::Mapper.new(inputs: inputs["association"], data: data, user: user1).perform
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(
inputs: inputs['conditional'],
data: data,
user: user1
).perform).to eq("true")
expect(
CustomWizard::Mapper.new(inputs: inputs["conditional"], data: data, 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'],
data: data,
user: user2
).perform).to eq(nil)
expect(
CustomWizard::Mapper.new(inputs: inputs["conditional"], data: data, user: user2).perform,
).to eq(nil)
end
it "maps when multiple conditions are met" do
expect(CustomWizard::Mapper.new(
inputs: inputs['conditional_multiple_pairs'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["conditional_multiple_pairs"],
data: data,
user: user1
).perform).to eq("true")
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'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["conditional_multiple_pairs"],
data: data,
user: user1
).perform).to eq(nil)
user: user1,
).perform,
).to eq(nil)
end
end
context "conditional validation" do
it "validates valid data" do
expect(CustomWizard::Mapper.new(
inputs: inputs['validation'],
data: data,
user: user1
).perform).to eq(true)
expect(
CustomWizard::Mapper.new(inputs: inputs["validation"], data: data, user: user1).perform,
).to eq(true)
end
it "does not validate invalid data" do
data["input_2"] = "value 3"
expect(CustomWizard::Mapper.new(
inputs: inputs['validation'],
data: data,
user: user1
).perform).to eq(false)
expect(
CustomWizard::Mapper.new(inputs: inputs["validation"], data: data, user: user1).perform,
).to eq(false)
end
context "using or condition" do
it "validates the data when all of the conditions are met" do
expect(CustomWizard::Mapper.new(
inputs: inputs['validation_multiple_pairs'],
expect(
CustomWizard::Mapper
.new(
inputs: inputs["validation_multiple_pairs"],
data: data,
user: user1,
opts: {
multiple: true
}
).perform.any?).to eq(true)
multiple: true,
},
)
.perform
.any?,
).to eq(true)
end
it "validates the data when one of the conditions are met" do
custom_data = data.dup
custom_data['input_1'] = 'value 3'
expect(CustomWizard::Mapper.new(
inputs: inputs['validation_multiple_pairs'],
custom_data["input_1"] = "value 3"
expect(
CustomWizard::Mapper
.new(
inputs: inputs["validation_multiple_pairs"],
data: custom_data,
user: user1,
opts: {
multiple: true
}
).perform.any?).to eq(true)
multiple: true,
},
)
.perform
.any?,
).to eq(true)
end
it "doesn't validate the data when none of the conditions are met" do
custom_data = data.dup
custom_data['input_1'] = 'value 3'
custom_data['input_2'] = 'value 4'
expect(CustomWizard::Mapper.new(
inputs: inputs['validation_multiple_pairs'],
custom_data["input_1"] = "value 3"
custom_data["input_2"] = "value 4"
expect(
CustomWizard::Mapper
.new(
inputs: inputs["validation_multiple_pairs"],
data: custom_data,
user: user1,
opts: {
multiple: true
}
).perform.any?).to eq(false)
multiple: true,
},
)
.perform
.any?,
).to eq(false)
end
end
end
it "maps text fields" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment_text'],
data: data,
user: user1
).perform).to eq("Value")
expect(
CustomWizard::Mapper.new(inputs: inputs["assignment_text"], data: data, user: user1).perform,
).to eq("Value")
end
it "maps user fields" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment_user_field'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["assignment_user_field"],
data: data,
user: user1
).perform).to eq("Angus")
user: user1,
).perform,
).to eq("Angus")
end
it "maps user field options" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment_user_field_options'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["assignment_user_field_options"],
data: data,
user: user1
).perform).to eq(["a", "b", "c"])
user: user1,
).perform,
).to eq(%w[a b c])
end
it "maps wizard fields" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment_wizard_field'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["assignment_wizard_field"],
data: data,
user: user1
).perform).to eq("value 1")
user: user1,
).perform,
).to eq("value 1")
end
it "maps wizard actions" do
expect(CustomWizard::Mapper.new(
inputs: inputs['assignment_wizard_action'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["assignment_wizard_action"],
data: data,
user: user1
).perform).to eq("value 2")
user: user1,
).perform,
).to eq("value 2")
end
context "interpolates" do
it "user fields" do
expect(CustomWizard::Mapper.new(
inputs: inputs['interpolate_user_field'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["interpolate_user_field"],
data: data,
user: user1
).perform).to eq("Name: Angus")
user: user1,
).perform,
).to eq("Name: Angus")
end
it "user emails" do
expect(CustomWizard::Mapper.new(
inputs: inputs['interpolate_user_email'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["interpolate_user_email"],
data: data,
user: user1
).perform).to eq("Email: angus@email.com")
user: user1,
).perform,
).to eq("Email: angus@email.com")
end
it "user options" do
user1.user_option.update_columns(email_level: UserOption.email_level_types[:never])
expect(CustomWizard::Mapper.new(
inputs: inputs['interpolate_user_option'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["interpolate_user_option"],
data: data,
user: user1
).perform).to eq("Email Level: #{UserOption.email_level_types[:never]}")
user: user1,
).perform,
).to eq("Email Level: #{UserOption.email_level_types[:never]}")
end
it "date" do
expect(CustomWizard::Mapper.new(
inputs: inputs['interpolate_timestamp'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["interpolate_timestamp"],
data: data,
user: user1
).perform).to eq("Time: #{Time.now.strftime("%B %-d, %Y")}")
user: user1,
).perform,
).to eq("Time: #{Time.now.strftime("%B %-d, %Y")}")
end
it "avatar" do
expect(CustomWizard::Mapper.new(
inputs: inputs['interpolate_avatar'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["interpolate_avatar"],
data: data,
user: user1
).perform).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
user: user1,
).perform,
).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
end
it "avatar with invalid size" do
avatar_inputs = inputs['interpolate_avatar'].dup
avatar_inputs = inputs["interpolate_avatar"].dup
avatar_inputs[0]["output"] = "Avatar: ![avatar](u{avatar.345})"
expect(CustomWizard::Mapper.new(
inputs: avatar_inputs,
data: data,
user: user1
).perform).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
expect(
CustomWizard::Mapper.new(inputs: avatar_inputs, data: data, user: user1).perform,
).to eq("Avatar: ![avatar](#{user1.small_avatar_url})")
end
it "avatar with valid size" do
avatar_inputs = inputs['interpolate_avatar'].dup
avatar_inputs = inputs["interpolate_avatar"].dup
avatar_inputs[0]["output"] = "Avatar: ![avatar](u{avatar.144})"
expect(CustomWizard::Mapper.new(
inputs: avatar_inputs,
data: data,
user: user1
).perform).to eq("Avatar: ![avatar](#{user1.avatar_template_url.gsub("{size}", "144")})")
expect(
CustomWizard::Mapper.new(inputs: avatar_inputs, data: data, user: user1).perform,
).to eq("Avatar: ![avatar](#{user1.avatar_template_url.gsub("{size}", "144")})")
end
end
it "handles not equal pairs" do
expect(CustomWizard::Mapper.new(
inputs: inputs['not_equals_pair'],
data: data,
user: user1
).perform).to eq(true)
expect(CustomWizard::Mapper.new(
inputs: inputs['not_equals_pair'],
data: data,
user: user2
).perform).to eq(false)
expect(
CustomWizard::Mapper.new(inputs: inputs["not_equals_pair"], data: data, user: user1).perform,
).to eq(true)
expect(
CustomWizard::Mapper.new(inputs: inputs["not_equals_pair"], data: data, user: user2).perform,
).to eq(false)
end
it "handles greater than pairs" do
expect(CustomWizard::Mapper.new(
inputs: inputs['greater_than_pair'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["greater_than_pair"],
data: data,
user: user1
).perform).to eq(true)
expect(CustomWizard::Mapper.new(
inputs: inputs['greater_than_pair'],
user: user1,
).perform,
).to eq(true)
expect(
CustomWizard::Mapper.new(
inputs: inputs["greater_than_pair"],
data: data,
user: user2
).perform).to eq(false)
user: user2,
).perform,
).to eq(false)
end
it "handles less than pairs" do
expect(CustomWizard::Mapper.new(
inputs: inputs['less_than_pair'],
data: data,
user: user1
).perform).to eq(false)
expect(CustomWizard::Mapper.new(
inputs: inputs['less_than_pair'],
data: data,
user: user2
).perform).to eq(true)
expect(
CustomWizard::Mapper.new(inputs: inputs["less_than_pair"], data: data, user: user1).perform,
).to eq(false)
expect(
CustomWizard::Mapper.new(inputs: inputs["less_than_pair"], data: data, 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'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["greater_than_or_equal_pair"],
data: data,
user: user1
).perform).to eq(true)
expect(CustomWizard::Mapper.new(
inputs: inputs['greater_than_or_equal_pair'],
user: user1,
).perform,
).to eq(true)
expect(
CustomWizard::Mapper.new(
inputs: inputs["greater_than_or_equal_pair"],
data: data,
user: user2
).perform).to eq(true)
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'],
expect(
CustomWizard::Mapper.new(
inputs: inputs["less_than_or_equal_pair"],
data: data,
user: user1
).perform).to eq(true)
expect(CustomWizard::Mapper.new(
inputs: inputs['less_than_or_equal_pair'],
user: user1,
).perform,
).to eq(true)
expect(
CustomWizard::Mapper.new(
inputs: inputs["less_than_or_equal_pair"],
data: data,
user: user2
).perform).to eq(true)
user: user2,
).perform,
).to eq(true)
end
it "handles regex pairs" do
expect(CustomWizard::Mapper.new(
inputs: inputs['regex_pair'],
data: data,
user: user1
).perform).to eq(true)
expect(CustomWizard::Mapper.new(
inputs: inputs['regex_pair'],
data: data,
user: user2
).perform).to eq(false)
expect(
CustomWizard::Mapper.new(inputs: inputs["regex_pair"], data: data, user: user1).perform,
).to eq(true)
expect(
CustomWizard::Mapper.new(inputs: inputs["regex_pair"], data: data, user: user2).perform,
).to eq(false)
end
it "handles shorthand pairs" do
expect(CustomWizard::Mapper.new(
inputs: inputs['shorthand_pair'],
data: data,
user: user1
).perform).to eq(false)
expect(
CustomWizard::Mapper.new(inputs: inputs["shorthand_pair"], data: data, user: user1).perform,
).to eq(false)
end
context "output templating" do
it "passes the correct values to the template" do
template = "w{step_1_field_1}"
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq(template_params["step_1_field_1"])
end
it "does not require a subscription" do
template = '{{ "w{step_1_field_1}" | size }}'
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq("5")
end
context "with a subscription" do
before do
enable_subscription("standard")
end
before { enable_subscription("standard") }
it "treats replaced values as string literals" do
template = '{{ "w{step_1_field_1}" | size }}'
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq(template_params["step_1_field_1"].size.to_s)
end
@ -436,26 +410,16 @@ describe CustomWizard::Mapper do
{%-endif-%}
LIQUID
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq("Correct")
end
it "can access data passed to render method as variable" do
template = "{{step_1_field_1.size}}"
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq(template_params["step_1_field_1"].size.to_s)
end
@ -464,10 +428,7 @@ describe CustomWizard::Mapper do
{{ "w{step_1_field_1}" | size}}
LIQUID
mapper = create_template_mapper(template_params, user1)
result = mapper.interpolate(
template.dup,
template: false,
)
result = mapper.interpolate(template.dup, template: false)
expect(result).to eq(template)
end
@ -480,11 +441,7 @@ describe CustomWizard::Mapper do
{%-endif-%}
LIQUID
mapper = create_template_mapper(template_params_object, user1)
result = mapper.interpolate(
template.dup,
template: true,
wizard: true
)
result = mapper.interpolate(template.dup, template: true, wizard: true)
expect(result).to eq("Correct")
end
@ -497,11 +454,7 @@ describe CustomWizard::Mapper do
{%-endif-%}
LIQUID
mapper = create_template_mapper(template_params_object, user1)
result = mapper.interpolate(
template.dup,
template: true,
wizard: true
)
result = mapper.interpolate(template.dup, template: true, wizard: true)
expect(result).to eq("Incorrect")
end
@ -510,13 +463,8 @@ describe CustomWizard::Mapper do
{% for object in step_1_field_1 %}{{object.text}} {% endfor %}
LIQUID
mapper = create_template_mapper(template_params_object_array, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq("Hello World ")
end
@ -527,13 +475,8 @@ describe CustomWizard::Mapper do
{{ entry }}
LIQUID
mapper = create_template_mapper(template_params_non_empty, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq(template_params_non_empty["step_1_field_3"])
end
@ -543,13 +486,8 @@ describe CustomWizard::Mapper do
{{ entry }}
LIQUID
mapper = create_template_mapper(template_params_multiple_non_empty, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq(template_params_multiple_non_empty["step_1_field_2"])
end
@ -561,13 +499,8 @@ describe CustomWizard::Mapper do
{%- endif -%}
LIQUID
mapper = create_template_mapper(template_params_empty, user1)
result = mapper.interpolate(
template.dup,
template: true,
user: true,
wizard: true,
value: true
)
result =
mapper.interpolate(template.dup, template: true, user: true, wizard: true, value: true)
expect(result).to eq("")
end
end

Datei anzeigen

@ -5,7 +5,9 @@ describe ::CustomWizard::RealtimeValidation::SimilarTopics do
let(:topic) { post.topic }
let(:category) { Fabricate(:category) }
let(:cat_post) { create_post(title: "matching similar topic slightly different", category: category) }
let(:cat_post) do
create_post(title: "matching similar topic slightly different", category: category)
end
let(:cat_topic) { cat_post.topic }
let(:user) { cat_post.user }

Datei anzeigen

@ -4,9 +4,7 @@ describe CustomWizard::Step do
let(:step_hash) { get_wizard_fixture("step/step") }
let(:field_hash) { get_wizard_fixture("field/field") }
before do
@step = CustomWizard::Step.new(step_hash[:id])
end
before { @step = CustomWizard::Step.new(step_hash[:id]) }
it "adds fields" do
@step.add_field(field_hash)

Datei anzeigen

@ -1,7 +1,7 @@
# frozen_string_literal: true
describe CustomWizard::Submission do
fab!(:user) { Fabricate(:user) }
fab!(:user)
fab!(:user2) { Fabricate(:user) }
let(:template_json) { get_wizard_fixture("wizard") }
let(:guest_id) { CustomWizard::Wizard.generate_guest_id }
@ -13,9 +13,7 @@ describe CustomWizard::Submission do
end
it "saves a user's submission" do
expect(
described_class.get(@wizard).fields["step_1_field_1"]
).to eq("I am user submission")
expect(described_class.get(@wizard).fields["step_1_field_1"]).to eq("I am user submission")
end
it "saves a guest's submission" do
@ -23,9 +21,7 @@ describe CustomWizard::Submission do
@wizard = CustomWizard::Wizard.create(template_json["id"], nil, guest_id)
described_class.new(@wizard, step_1_field_1: "I am guest submission").save
expect(
described_class.get(@wizard).fields["step_1_field_1"]
).to eq("I am guest submission")
expect(described_class.get(@wizard).fields["step_1_field_1"]).to eq("I am guest submission")
end
describe "#list" do
@ -41,7 +37,11 @@ describe CustomWizard::Submission do
@count = CustomWizard::Submission::PAGE_LIMIT + 20
@count.times do |index|
described_class.new(@wizard, step_1_field_1: "I am user submission #{index + 1}", submitted_at: Time.now + (index + 1).minutes).save
described_class.new(
@wizard,
step_1_field_1: "I am user submission #{index + 1}",
submitted_at: Time.now + (index + 1).minutes,
).save
end
described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save
described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save
@ -59,11 +59,15 @@ describe CustomWizard::Submission do
it "paginates submission lists" do
@wizard.user = nil
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 2) - CustomWizard::Submission::PAGE_LIMIT)
expect(described_class.list(@wizard, page: 1).submissions.size).to eq(
(@count + 2) - CustomWizard::Submission::PAGE_LIMIT,
)
end
it "orders submissions by submitted_at" do
expect(described_class.list(@wizard).submissions.first.submitted_at.to_datetime.change(usec: 0)).to eq((Time.now + @count.minutes).change(usec: 0))
expect(
described_class.list(@wizard).submissions.first.submitted_at.to_datetime.change(usec: 0),
).to eq((Time.now + @count.minutes).change(usec: 0))
end
end
@ -83,9 +87,7 @@ describe CustomWizard::Submission do
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
described_class.new(@wizard, step_1_field_1: "I am the third submission").save
sub_data = PluginStore.get("#{@wizard.id}_submissions", @wizard.user.id)
sub_data.each do |sub|
sub['updated_at'] = nil
end
sub_data.each { |sub| sub["updated_at"] = nil }
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
builder.build
@ -101,7 +103,7 @@ describe CustomWizard::Submission do
freeze_time Time.now + 2
described_class.new(@wizard, step_1_field_1: "I am the third submission").save
sub_data = PluginStore.get("#{@wizard.id}_submissions", @wizard.user.id)
sub_data[0]['updated_at'] = nil
sub_data[0]["updated_at"] = nil
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)

Datei anzeigen

@ -5,19 +5,17 @@ describe CustomWizard::Subscription do
let!(:business_product_id) { SecureRandom.hex(8) }
let!(:standard_product_id) { SecureRandom.hex(8) }
let!(:community_product_id) { SecureRandom.hex(8) }
let!(:product_slugs) {
let!(:product_slugs) do
{
"#{business_product_id}" => "business",
"#{standard_product_id}" => "standard",
"#{community_product_id}" => "community"
}
"#{community_product_id}" => "community",
}
end
context "with subscription client gem mocked out" do
context "without a subscription" do
before do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(nil)
end
before { DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(nil) }
it "has none type" do
expect(described_class.type).to eq(:none)
@ -33,31 +31,43 @@ describe CustomWizard::Subscription do
end
context "with subscriptions" do
def get_subscription_result(product_ids)
result = DiscourseSubscriptionClient::Subscriptions::Result.new
result.supplier = SubscriptionClientSupplier.new(products: product_slugs)
result.resource = SubscriptionClientResource.new
result.subscriptions = product_ids.map { |product_id| ::SubscriptionClientSubscription.new(product_id: product_id) }
result.subscriptions =
product_ids.map do |product_id|
::SubscriptionClientSubscription.new(product_id: product_id)
end
result.products = product_slugs
result
end
let!(:business_subscription_result) { get_subscription_result([business_product_id]) }
let!(:standard_subscription_result) { get_subscription_result([standard_product_id]) }
let!(:community_subscription_result) { get_subscription_result([community_product_id]) }
let!(:multiple_subscription_result) { get_subscription_result([community_product_id, business_product_id]) }
let!(:multiple_subscription_result) do
get_subscription_result([community_product_id, business_product_id])
end
it "handles mapped values" do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(standard_subscription_result)
expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(true)
expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(
true,
)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(community_subscription_result)
expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(false)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(
community_subscription_result,
)
expect(described_class.includes?(:wizard, :permitted, guests_permitted["permitted"])).to eq(
false,
)
end
context "with a standard subscription" do
before do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(standard_subscription_result)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(
standard_subscription_result,
)
end
it "detects standard type" do
@ -65,17 +75,19 @@ describe CustomWizard::Subscription do
end
it "standard features are included" do
expect(described_class.includes?(:wizard, :type, 'send_message')).to eq(true)
expect(described_class.includes?(:wizard, :type, "send_message")).to eq(true)
end
it "business features are not included" do
expect(described_class.includes?(:action, :type, 'create_category')).to eq(false)
expect(described_class.includes?(:action, :type, "create_category")).to eq(false)
end
end
context "with a business subscription" do
before do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(business_subscription_result)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(
business_subscription_result,
)
end
it "detects business type" do
@ -83,13 +95,15 @@ describe CustomWizard::Subscription do
end
it "business features are included" do
expect(described_class.includes?(:action, :type, 'create_category')).to eq(true)
expect(described_class.includes?(:action, :type, "create_category")).to eq(true)
end
end
context "with a community subscription" do
before do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(community_subscription_result)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(
community_subscription_result,
)
end
it "detects community type" do
@ -97,13 +111,15 @@ describe CustomWizard::Subscription do
end
it "community features are included" do
expect(described_class.includes?(:action, :type, 'create_category')).to eq(true)
expect(described_class.includes?(:action, :type, "create_category")).to eq(true)
end
end
context "with multiple subscriptions" do
before do
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(multiple_subscription_result)
DiscourseSubscriptionClient.stubs(:find_subscriptions).returns(
multiple_subscription_result,
)
end
it "detects correct type in hierarchy" do
@ -114,22 +130,16 @@ describe CustomWizard::Subscription do
end
context "with environment variable" do
before do
ENV["CUSTOM_WIZARD_PRODUCT_SLUG"] = "standard"
end
before { ENV["CUSTOM_WIZARD_PRODUCT_SLUG"] = "standard" }
after do
ENV["CUSTOM_WIZARD_PRODUCT_SLUG"] = nil
end
after { ENV["CUSTOM_WIZARD_PRODUCT_SLUG"] = nil }
it "enables the relevant subscription" do
expect(described_class.type).to eq(:standard)
end
context "with a subscription" do
before do
enable_subscription("business")
end
before { enable_subscription("business") }
it "respects the subscription" do
expect(described_class.type).to eq(:business)

Datei anzeigen

@ -1,152 +1,133 @@
# frozen_string_literal: true
describe CustomWizard::Template do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:template_json) { get_wizard_fixture("wizard") }
let(:permitted_json) { get_wizard_fixture("wizard/permitted") }
fab!(:upload) { Fabricate(:upload) }
fab!(:upload)
before do
CustomWizard::Template.save(template_json, skip_jobs: true)
end
before { CustomWizard::Template.save(template_json, skip_jobs: true) }
it "saves wizard templates" do
expect(
PluginStoreRow.exists?(
plugin_name: 'custom_wizard',
key: 'super_mega_fun_wizard'
)
PluginStoreRow.exists?(plugin_name: "custom_wizard", key: "super_mega_fun_wizard"),
).to eq(true)
end
it "finds wizard templates" do
expect(
CustomWizard::Template.find('super_mega_fun_wizard')['id']
).to eq('super_mega_fun_wizard')
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)
CustomWizard::Template.remove("super_mega_fun_wizard")
expect(CustomWizard::Template.find("super_mega_fun_wizard")).to eq(nil)
end
it "removes user wizard redirects if template is removed" do
user.custom_fields['redirect_to_wizard'] = 'super_mega_fun_wizard'
user.custom_fields["redirect_to_wizard"] = "super_mega_fun_wizard"
user.save_custom_fields(true)
CustomWizard::Template.remove('super_mega_fun_wizard')
expect(user.reload.custom_fields['redirect_to_wizard']).to eq(nil)
CustomWizard::Template.remove("super_mega_fun_wizard")
expect(user.reload.custom_fields["redirect_to_wizard"]).to eq(nil)
end
it "checks for wizard template existence" do
expect(
CustomWizard::Template.exists?('super_mega_fun_wizard')
).to eq(true)
expect(CustomWizard::Template.exists?("super_mega_fun_wizard")).to eq(true)
end
context "upload references" do
it "are added if a wizard has a step banner" do
template_json['steps'][0]['banner'] = upload.url
template_json['steps'][0]['banner_upload_id'] = upload.id
template_json["steps"][0]["banner"] = upload.url
template_json["steps"][0]["banner_upload_id"] = upload.id
CustomWizard::Template.save(template_json, skip_jobs: true)
wizard_record = CustomWizard::Template.find_record(template_json["id"])
expect(
UploadReference.exists?(
upload_id: upload.id,
target_type: "PluginStoreRow",
target_id: wizard_record.id
)
target_id: wizard_record.id,
),
).to eq(true)
end
it "are added if a wizard has a field image" do
template_json['steps'][0]["fields"][0]['image'] = upload.url
template_json['steps'][0]["fields"][0]['image_upload_id'] = upload.id
template_json["steps"][0]["fields"][0]["image"] = upload.url
template_json["steps"][0]["fields"][0]["image_upload_id"] = upload.id
CustomWizard::Template.save(template_json, skip_jobs: true)
wizard_record = CustomWizard::Template.find_record(template_json["id"])
expect(
UploadReference.exists?(
upload_id: upload.id,
target_type: "PluginStoreRow",
target_id: wizard_record.id
)
target_id: wizard_record.id,
),
).to eq(true)
end
it "are removed if a wizard step banner is removed" do
template_json['steps'][0]['banner'] = upload.url
template_json['steps'][0]['banner_upload_id'] = upload.id
template_json["steps"][0]["banner"] = upload.url
template_json["steps"][0]["banner_upload_id"] = upload.id
CustomWizard::Template.save(template_json, skip_jobs: true)
template_json['steps'][0]['banner'] = nil
template_json['steps'][0]['banner_upload_id'] = nil
template_json["steps"][0]["banner"] = nil
template_json["steps"][0]["banner_upload_id"] = nil
CustomWizard::Template.save(template_json, skip_jobs: true)
wizard_record = CustomWizard::Template.find_record(template_json["id"])
expect(
UploadReference.exists?(target_type: "PluginStoreRow")
).to eq(false)
expect(UploadReference.exists?(target_type: "PluginStoreRow")).to eq(false)
end
it "are removed if a wizard field image is removed" do
template_json['steps'][0]["fields"][0]['image'] = upload.url
template_json['steps'][0]["fields"][0]['image_upload_id'] = upload.id
template_json["steps"][0]["fields"][0]["image"] = upload.url
template_json["steps"][0]["fields"][0]["image_upload_id"] = upload.id
CustomWizard::Template.save(template_json, skip_jobs: true)
template_json['steps'][0]["fields"][0]['image'] = nil
template_json['steps'][0]["fields"][0]['image_upload_id'] = nil
template_json["steps"][0]["fields"][0]["image"] = nil
template_json["steps"][0]["fields"][0]["image_upload_id"] = nil
CustomWizard::Template.save(template_json, skip_jobs: true)
wizard_record = CustomWizard::Template.find_record(template_json["id"])
expect(
UploadReference.exists?(target_type: "PluginStoreRow")
).to eq(false)
expect(UploadReference.exists?(target_type: "PluginStoreRow")).to eq(false)
end
it "are removed if a wizard is removed" do
template_json['steps'][0]["fields"][0]['image'] = upload.url
template_json['steps'][0]["fields"][0]['image_upload_id'] = upload.id
template_json["steps"][0]["fields"][0]["image"] = upload.url
template_json["steps"][0]["fields"][0]["image_upload_id"] = upload.id
CustomWizard::Template.save(template_json, skip_jobs: true)
CustomWizard::Template.remove(template_json["id"])
expect(
UploadReference.exists?(target_type: "PluginStoreRow")
).to eq(false)
expect(UploadReference.exists?(target_type: "PluginStoreRow")).to eq(false)
end
end
context "wizard template list" do
before do
enable_subscription('standard')
enable_subscription("standard")
template_json_2 = template_json.dup
template_json_2["id"] = 'super_mega_fun_wizard_2'
template_json_2["permitted"] = permitted_json['permitted']
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["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)
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)
expect(CustomWizard::Template.list(setting: "after_signup").length).to eq(1)
end
it "can be ordered" do
expect(
CustomWizard::Template.list(
order: "(value::json ->> 'permitted') IS NOT NULL DESC"
).first['id']
).to eq('super_mega_fun_wizard_2')
CustomWizard::Template.list(order: "(value::json ->> 'permitted') IS NOT NULL DESC").first[
"id"
],
).to eq("super_mega_fun_wizard_2")
end
end
@ -160,15 +141,15 @@ describe CustomWizard::Template do
@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
it "if disabled clears jobs after wizard is saved" do
CustomWizard::Template.save(@after_time_template)
@after_time_template['after_time'] = false
@after_time_template["after_time"] = false
expect_not_enqueued_with(job: :set_after_time_wizard) do
CustomWizard::Template.save(@after_time_template)

Datei anzeigen

@ -1,7 +1,7 @@
# frozen_string_literal: true
describe CustomWizard::TemplateValidator do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:template) { get_wizard_fixture("wizard") }
let(:create_category) { get_wizard_fixture("actions/create_category") }
let(:user_condition) { get_wizard_fixture("condition/user_condition") }
@ -11,26 +11,20 @@ describe CustomWizard::TemplateValidator do
let(:upload_field) { get_wizard_fixture("field/upload") }
let(:validation_condition) { get_wizard_fixture("condition/validation_condition") }
let(:valid_liquid_template) {
<<-LIQUID.strip
let(:valid_liquid_template) { <<-LIQUID.strip }
{%- assign hello = "Topic Form 1" %}
LIQUID
}
let(:invalid_liquid_template) {
<<-LIQUID.strip
let(:invalid_liquid_template) { <<-LIQUID.strip }
{%- assign hello = "Topic Form 1" %
LIQUID
}
let(:liquid_syntax_error) {
let(:liquid_syntax_error) do
"Liquid syntax error: Tag '{%' was not properly terminated with regexp: /\\%\\}/"
}
end
def expect_validation_success
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
def expect_validation_failure(object_id, message)
@ -40,23 +34,17 @@ describe CustomWizard::TemplateValidator do
end
it "validates valid templates" do
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
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)
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)
expect(CustomWizard::TemplateValidator.new(template, create: true).perform).to eq(false)
end
it "only allows one after signup wizard at a time" do
@ -70,7 +58,7 @@ describe CustomWizard::TemplateValidator do
validator = CustomWizard::TemplateValidator.new(template)
expect(validator.perform).to eq(false)
expect(validator.errors.first.type).to eq(
I18n.t("wizard.validation.after_signup", wizard_id: wizard_id)
I18n.t("wizard.validation.after_signup", wizard_id: wizard_id),
)
end
@ -86,138 +74,106 @@ describe CustomWizard::TemplateValidator do
validator = CustomWizard::TemplateValidator.new(template)
expect(validator.perform).to eq(false)
expect(validator.errors.first.type).to eq(
I18n.t("wizard.validation.after_signup_after_time")
)
expect(validator.errors.first.type).to eq(I18n.t("wizard.validation.after_signup_after_time"))
end
it "validates after time settings" do
template[:after_time] = true
template[:after_time_scheduled] = (Time.now + 3.hours).iso8601
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
expect(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"
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
context "without subscription" do
it "invalidates subscription wizard attributes" do
template[:permitted] = permitted_json['permitted']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
template[:permitted] = permitted_json["permitted"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
it "invalidates subscription step attributes" do
template[:steps][0][:condition] = user_condition['condition']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
template[:steps][0][:condition] = user_condition["condition"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
it "invalidates subscription field attributes" do
template[:steps][0][:fields][0][:condition] = user_condition['condition']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
template[:steps][0][:fields][0][:condition] = user_condition["condition"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
it "invalidates subscription actions" do
template[:actions] << create_category
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
end
context "with subscription" do
before do
enable_subscription("business")
end
before { enable_subscription("business") }
it "validates wizard attributes" do
template[:permitted] = permitted_json['permitted']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
template[:permitted] = permitted_json["permitted"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
it "validates user-only features" do
template[:permitted] = guests_permitted['permitted']
template[:permitted] = guests_permitted["permitted"]
template[:steps][0][:fields] << upload_field
validator = CustomWizard::TemplateValidator.new(template)
expect(validator.perform).to eq(false)
errors = validator.errors.to_a
expect(errors).to include(
I18n.t("wizard.validation.not_permitted_for_guests", object_id: "step_2_field_7")
I18n.t("wizard.validation.not_permitted_for_guests", object_id: "step_2_field_7"),
)
end
it "validates step attributes" do
template[:steps][0][:condition] = user_condition['condition']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
template[:steps][0][:condition] = user_condition["condition"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
it "validates field attributes" do
template[:steps][0][:fields][0][:condition] = user_condition['condition']
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
template[:steps][0][:fields][0][:condition] = user_condition["condition"]
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
it "validates actions" do
template[:actions] << create_category
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
it "validates settings with validation conditions" do
template[:permitted] = validation_condition["condition"]
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(true)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(true)
end
end
context "steps" do
CustomWizard::TemplateValidator.required[:step].each do |attribute|
it "invalidates if \"#{attribute.to_s}\" is not present" do
it "invalidates if \"#{attribute}\" is not present" do
template[:steps][0][attribute] = nil
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
end
end
context "fields" do
CustomWizard::TemplateValidator.required[:field].each do |attribute|
it "invalidates if \"#{attribute.to_s}\" is not present" do
it "invalidates if \"#{attribute}\" is not present" do
template[:steps][0][:fields][0][attribute] = nil
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
end
end
context "actions" do
CustomWizard::TemplateValidator.required[:action].each do |attribute|
it "invalidates if \"#{attribute.to_s}\" is not present" do
it "invalidates if \"#{attribute}\" is not present" do
template[:actions][0][attribute] = nil
expect(
CustomWizard::TemplateValidator.new(template).perform
).to eq(false)
expect(CustomWizard::TemplateValidator.new(template).perform).to eq(false)
end
end
end

Datei anzeigen

@ -1,13 +1,13 @@
# frozen_string_literal: true
describe CustomWizard::UpdateValidator do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:template) { get_wizard_fixture("wizard") }
let(:url_field) { get_wizard_fixture("field/url") }
before do
CustomWizard::Template.save(template, skip_jobs: true)
@template = CustomWizard::Template.find('super_mega_fun_wizard')
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
def perform_validation(step_id, submission)
@ -17,7 +17,7 @@ describe CustomWizard::UpdateValidator do
updater
end
it 'applies min length to text type fields' do
it "applies min length to text type fields" do
min_length = 3
@template[:steps][0][:fields][0][:min_length] = min_length
@ -25,34 +25,35 @@ describe CustomWizard::UpdateValidator do
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_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')
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_2: "Te")
expect(updater.errors.messages[:step_1_field_2].first).to eq(
I18n.t("wizard.field.too_short", label: "Textarea", min: min_length),
)
end
it 'prevents submission if the length is over the max length' do
it "prevents submission if the length is over the max length" do
max_length = 100
@template[:steps][0][:fields][0][:max_length] = max_length
@template[:steps][0][:fields][1][:max_length] = max_length
CustomWizard::Template.save(@template)
long_string = "Our Competitive Capability solution offers platforms a suite of wholesale offerings. In the future, will you be able to effectively revolutionize synergies in your business? In the emerging market space, industry is ethically investing its mission critical executive searches. Key players will take ownership of their capabilities by iteratively right-sizing world-class visibilities. "
updater = perform_validation('step_1', step_1_field_1: long_string)
expect(
updater.errors.messages[:step_1_field_1].first
).to eq(I18n.t('wizard.field.too_long', label: 'Text', max: max_length))
long_string =
"Our Competitive Capability solution offers platforms a suite of wholesale offerings. In the future, will you be able to effectively revolutionize synergies in your business? In the emerging market space, industry is ethically investing its mission critical executive searches. Key players will take ownership of their capabilities by iteratively right-sizing world-class visibilities. "
updater = perform_validation("step_1", step_1_field_1: long_string)
expect(updater.errors.messages[:step_1_field_1].first).to eq(
I18n.t("wizard.field.too_long", label: "Text", max: max_length),
)
updater = perform_validation('step_1', step_1_field_2: long_string)
expect(
updater.errors.messages[:step_1_field_2].first
).to eq(I18n.t('wizard.field.too_long', label: 'Textarea', max: max_length))
updater = perform_validation("step_1", step_1_field_2: long_string)
expect(updater.errors.messages[:step_1_field_2].first).to eq(
I18n.t("wizard.field.too_long", label: "Textarea", max: max_length),
)
end
it "allows submission if the length is under or equal to the max length" do
@ -62,16 +63,13 @@ describe CustomWizard::UpdateValidator do
@template[:steps][0][:fields][1][:max_length] = max_length
CustomWizard::Template.save(@template)
hundred_chars_string = "This is a line, exactly hundred characters long and not more even a single character more than that."
updater = perform_validation('step_1', step_1_field_1: hundred_chars_string)
expect(
updater.errors.messages[:step_1_field_1].first
).to eq(nil)
hundred_chars_string =
"This is a line, exactly hundred characters long and not more even a single character more than that."
updater = perform_validation("step_1", step_1_field_1: hundred_chars_string)
expect(updater.errors.messages[:step_1_field_1].first).to eq(nil)
updater = perform_validation('step_1', step_1_field_2: hundred_chars_string)
expect(
updater.errors.messages[:step_1_field_2].first
).to eq(nil)
updater = perform_validation("step_1", step_1_field_2: hundred_chars_string)
expect(updater.errors.messages[:step_1_field_2].first).to eq(nil)
end
it "applies min length only if the input is non-empty" do
@ -81,10 +79,8 @@ describe CustomWizard::UpdateValidator do
CustomWizard::Template.save(@template)
updater = perform_validation('step_1', step_1_field_1: '')
expect(
updater.errors.messages[:step_1_field_1].first
).to eq(nil)
updater = perform_validation("step_1", step_1_field_1: "")
expect(updater.errors.messages[:step_1_field_1].first).to eq(nil)
end
it "applies max length only if the input is non-empty" do
@ -93,93 +89,81 @@ describe CustomWizard::UpdateValidator do
@template[:steps][0][:fields][0][:max_length] = max_length
CustomWizard::Template.save(@template)
updater = perform_validation('step_1', step_1_field_1: "")
expect(
updater.errors.messages[:step_1_field_1].first
).to eq(nil)
updater = perform_validation("step_1", step_1_field_1: "")
expect(updater.errors.messages[:step_1_field_1].first).to eq(nil)
end
it 'standardises boolean entries' do
updater = perform_validation('step_2', step_2_field_5: 'false')
expect(updater.submission['step_2_field_5']).to eq(false)
it "standardises boolean entries" 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
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)
expect(
updater.errors.messages[:step_1_field_2].first
).to eq(I18n.t('wizard.field.required', label: 'Textarea'))
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"),
)
end
context "subscription fields" do
before do
enable_subscription("standard")
before { enable_subscription("standard") }
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 '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
it "does not validate url fields with non-url inputs" do
template[:steps][0][:fields] << url_field
CustomWizard::Template.save(template)
updater = perform_validation('step_1', step_2_field_6: 'discourse')
expect(
updater.errors.messages[:step_2_field_6].first
).to eq(I18n.t('wizard.field.not_url', label: 'Url'))
updater = perform_validation("step_1", 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)
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
it 'validates date fields' do
it "validates date fields" do
@template[:steps][1][:fields][0][:format] = "DD-MM-YYYY"
CustomWizard::Template.save(@template)
updater = perform_validation('step_2', step_2_field_1: '13-11-2021')
expect(
updater.errors.messages[:step_2_field_1].first
).to eq(nil)
updater = perform_validation("step_2", step_2_field_1: "13-11-2021")
expect(updater.errors.messages[:step_2_field_1].first).to eq(nil)
end
it 'doesn\'t validate date field if the format is not respected' do
@template[:steps][1][:fields][0][:format] = "MM-DD-YYYY"
CustomWizard::Template.save(@template)
updater = perform_validation('step_2', step_2_field_1: '13-11-2021')
expect(
updater.errors.messages[:step_2_field_1].first
).to eq(I18n.t('wizard.field.invalid_date'))
updater = perform_validation("step_2", step_2_field_1: "13-11-2021")
expect(updater.errors.messages[:step_2_field_1].first).to eq(
I18n.t("wizard.field.invalid_date"),
)
end
it 'validates date time fields' do
it "validates date time fields" do
@template[:steps][1][:fields][2][:format] = "DD-MM-YYYY HH:mm:ss"
CustomWizard::Template.save(@template)
updater = perform_validation('step_2', step_2_field_3: '13-11-2021 09:15:00')
expect(
updater.errors.messages[:step_2_field_3].first
).to eq(nil)
updater = perform_validation("step_2", step_2_field_3: "13-11-2021 09:15:00")
expect(updater.errors.messages[:step_2_field_3].first).to eq(nil)
end
it 'doesn\'t validate date time field if the format is not respected' do
@template[:steps][1][:fields][2][:format] = "MM-DD-YYYY HH:mm:ss"
CustomWizard::Template.save(@template)
updater = perform_validation('step_2', step_2_field_3: '13-11-2021 09:15')
expect(
updater.errors.messages[:step_2_field_3].first
).to eq(I18n.t('wizard.field.invalid_date'))
updater = perform_validation("step_2", step_2_field_3: "13-11-2021 09:15")
expect(updater.errors.messages[:step_2_field_3].first).to eq(
I18n.t("wizard.field.invalid_date"),
)
end
end

Datei anzeigen

@ -19,9 +19,7 @@ describe CustomWizard::Wizard do
end
def append_steps
template_json['steps'].each do |step_template|
@wizard.append_step(step_template['id'])
end
template_json["steps"].each { |step_template| @wizard.append_step(step_template["id"]) }
@wizard.update!
end
@ -30,7 +28,7 @@ describe CustomWizard::Wizard do
action: CustomWizard::UserHistory.actions[:step],
actor_id: actor_id,
context: wizard.id,
subject: step_id
subject: step_id,
)
@wizard.update!
end
@ -47,13 +45,13 @@ describe CustomWizard::Wizard do
end
it "appends steps with custom indexes" do
template_json['steps'][0]['index'] = 2
template_json['steps'][1]['index'] = 1
template_json['steps'][2]['index'] = 0
template_json["steps"][0]["index"] = 2
template_json["steps"][1]["index"] = 1
template_json["steps"][2]["index"] = 0
template_json['steps'].each do |step_template|
@wizard.append_step(step_template['id']) do |step|
step.index = step_template['index'] if step_template['index']
template_json["steps"].each do |step_template|
@wizard.append_step(step_template["id"]) do |step|
step.index = step_template["index"] if step_template["index"]
end
end
@ -71,38 +69,35 @@ describe CustomWizard::Wizard do
it "determines the user's current step" do
append_steps
expect(@wizard.start).to eq('step_1')
progress_step('step_1')
expect(@wizard.start).to eq('step_2')
expect(@wizard.start).to eq("step_1")
progress_step("step_1")
expect(@wizard.start).to eq("step_2")
end
it "determines the user's current step if steps are added" do
append_steps
progress_step('step_1')
progress_step('step_2')
progress_step("step_1")
progress_step("step_2")
progress_step("step_3")
fourth_step = step_json.dup
fourth_step['id'] = "step_4"
fourth_step["id"] = "step_4"
template = template_json.dup
template['steps'] << fourth_step
template["steps"] << fourth_step
CustomWizard::Template.save(template, skip_jobs: true)
wizard = CustomWizard::Wizard.new(template, user)
template['steps'].each do |step_template|
wizard.append_step(step_template['id'])
end
template["steps"].each { |step_template| wizard.append_step(step_template["id"]) }
expect(wizard.steps.size).to eq(4)
expect(wizard.start).to eq(nil)
end
it "creates a step updater" do
expect(
@wizard.create_updater('step_1', step_1_field_1: "Text input")
.class
).to eq(CustomWizard::StepUpdater)
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
@ -133,8 +128,8 @@ describe CustomWizard::Wizard do
progress_step("step_2")
progress_step("step_3")
template_json['after_time'] = true
template_json['after_time_scheduled'] = Time.now + 3.hours
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(true)
@ -149,9 +144,9 @@ describe CustomWizard::Wizard do
progress_step("step_2")
progress_step("step_3")
template_json['after_time'] = true
template_json['multiple_submissions'] = true
template_json['after_time_scheduled'] = Time.now + 3.hours
template_json["after_time"] = true
template_json["multiple_submissions"] = true
template_json["after_time_scheduled"] = Time.now + 3.hours
wizard = CustomWizard::Wizard.new(template_json, user)
expect(wizard.completed?).to eq(false)
@ -159,45 +154,31 @@ describe CustomWizard::Wizard do
end
context "with subscription" do
before do
enable_subscription("standard")
end
before { enable_subscription("standard") }
it "permits admins" do
expect(
CustomWizard::Wizard.new(@permitted_template, admin_user).permitted?
).to eq(true)
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)
expect(CustomWizard::Wizard.new(@permitted_template, trusted_user).permitted?).to eq(true)
end
it "permits everyone if everyone is permitted" do
@permitted_template['permitted'][0]['output'] = Group::AUTO_GROUPS[:everyone]
expect(
CustomWizard::Wizard.new(@permitted_template, user).permitted?
).to eq(true)
@permitted_template["permitted"][0]["output"] = Group::AUTO_GROUPS[:everyone]
expect(CustomWizard::Wizard.new(@permitted_template, user).permitted?).to eq(true)
end
it "does not permit unpermitted users" do
expect(
CustomWizard::Wizard.new(@permitted_template, user).permitted?
).to eq(false)
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)
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)
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
@ -209,9 +190,7 @@ describe CustomWizard::Wizard do
@permitted_template["multiple_submissions"] = true
expect(
CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access?
).to eq(true)
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
@ -221,27 +200,21 @@ describe CustomWizard::Wizard do
progress_step("step_2", actor_id: trusted_user.id)
progress_step("step_3", actor_id: trusted_user.id)
@permitted_template['multiple_submissions'] = false
@permitted_template["multiple_submissions"] = false
expect(
CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access?
).to eq(false)
expect(CustomWizard::Wizard.new(@permitted_template, trusted_user).can_access?).to eq(false)
end
it "sets wizard redirects if user is permitted" do
CustomWizard::Template.save(@permitted_template, skip_jobs: true)
CustomWizard::Wizard.set_user_redirect('super_mega_fun_wizard', trusted_user)
expect(
trusted_user.custom_fields['redirect_to_wizard']
).to eq("super_mega_fun_wizard")
CustomWizard::Wizard.set_user_redirect("super_mega_fun_wizard", trusted_user)
expect(trusted_user.custom_fields["redirect_to_wizard"]).to eq("super_mega_fun_wizard")
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_user_redirect('super_mega_fun_wizard', user)
expect(
trusted_user.custom_fields['redirect_to_wizard']
).to eq(nil)
CustomWizard::Wizard.set_user_redirect("super_mega_fun_wizard", user)
expect(trusted_user.custom_fields["redirect_to_wizard"]).to eq(nil)
end
end
@ -249,47 +222,39 @@ describe CustomWizard::Wizard do
before do
enable_subscription("standard")
@wizard.restart_on_revisit = true
CustomWizard::Template.save(
CustomWizard::WizardSerializer.new(@wizard, root: false).as_json
)
CustomWizard::Template.save(CustomWizard::WizardSerializer.new(@wizard, root: false).as_json)
end
it "returns to step 1 if option to clear submissions on each visit is set" do
append_steps
expect(@wizard.unfinished?).to eq(true)
progress_step('step_1')
expect(@wizard.start).to eq('step_1')
progress_step("step_1")
expect(@wizard.start).to eq("step_1")
end
end
context "with subscription and guest wizard" do
before do
enable_subscription("standard")
end
before { enable_subscription("standard") }
it "permits admins" do
expect(
CustomWizard::Wizard.new(@guests_permitted_template, admin_user).permitted?
).to eq(true)
expect(CustomWizard::Wizard.new(@guests_permitted_template, admin_user).permitted?).to eq(
true,
)
end
it "permits regular users" do
expect(
CustomWizard::Wizard.new(@guests_permitted_template, user).permitted?
).to eq(true)
expect(CustomWizard::Wizard.new(@guests_permitted_template, user).permitted?).to eq(true)
end
it "permits guests" do
expect(
CustomWizard::Wizard.new(@guests_permitted_template, nil, "guest123").permitted?
CustomWizard::Wizard.new(@guests_permitted_template, nil, "guest123").permitted?,
).to eq(true)
end
end
context "submissions" do
before do
CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission").save
end
before { CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission").save }
it "lists the user's submissions" do
expect(@wizard.submissions.length).to eq(1)
@ -306,12 +271,12 @@ describe CustomWizard::Wizard 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["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["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)
@ -323,7 +288,7 @@ describe CustomWizard::Wizard do
end
it "returns the first after signup wizard" do
expect(CustomWizard::Wizard.after_signup(user).id).to eq('super_mega_fun_wizard_3')
expect(CustomWizard::Wizard.after_signup(user).id).to eq("super_mega_fun_wizard_3")
end
it "lists prompt completion wizards" do
@ -331,7 +296,8 @@ describe CustomWizard::Wizard do
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)
wizard_2 =
CustomWizard::Wizard.new(CustomWizard::Template.find("super_mega_fun_wizard_2"), user)
progress_step("step_1", wizard: wizard_2)
progress_step("step_2", wizard: wizard_2)
progress_step("step_3", wizard: wizard_2)

Datei anzeigen

@ -5,12 +5,12 @@ describe DiscoursePluginStatistics::Plugin do
describe "#discourse_custom_wizard" do
before do
enable_subscription('standard')
enable_subscription("standard")
CustomWizard::Template.save(template_json, skip_jobs: true)
template_json_2 = template_json.dup
template_json_2["id"] = 'super_mega_fun_wizard_2'
template_json_2["id"] = "super_mega_fun_wizard_2"
CustomWizard::Template.save(template_json_2, skip_jobs: true)
@data = DiscoursePluginStatistics::Plugin.discourse_custom_wizard
@ -21,7 +21,7 @@ describe DiscoursePluginStatistics::Plugin do
end
it "includes the subscription type" do
expect(@data[:subscription_type]).to eq('standard')
expect(@data[:subscription_type]).to eq("standard")
end
it "includes a count of features being used across all wizards" do
@ -36,7 +36,7 @@ describe DiscoursePluginStatistics::Plugin do
step: {
required_data: 0,
permitted_params: 0,
force_final: 0
force_final: 0,
},
field: {
condition: 0,
@ -60,7 +60,7 @@ describe DiscoursePluginStatistics::Plugin do
topic: 0,
user_selector: 0,
},
realtime_validations: 0
realtime_validations: 0,
},
action: {
type: {
@ -75,8 +75,8 @@ describe DiscoursePluginStatistics::Plugin do
add_to_group: 0,
create_group: 0,
create_category: 0,
}
}
},
},
)
end
end

Datei anzeigen

@ -1,17 +1,19 @@
# frozen_string_literal: true
describe "custom field extensions" do
fab!(:topic) { Fabricate(:topic) }
fab!(:post) { Fabricate(:post) }
fab!(:category) { Fabricate(:category) }
fab!(:group) { Fabricate(:group) }
fab!(:user) { Fabricate(:user) }
fab!(:topic)
fab!(:post)
fab!(:category)
fab!(:group)
fab!(:user)
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
let(:subscription_custom_field_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
let(:subscription_custom_field_json) do
get_wizard_fixture("custom_field/subscription_custom_fields")
end
before do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
custom_field = CustomWizard::CustomField.new(nil, field_json)
custom_field.save
end
@ -27,10 +29,11 @@ describe "custom field extensions" do
topic.custom_fields["topic_field_1"] = true
topic.save_custom_fields(true)
serializer = TopicViewSerializer.new(
serializer =
TopicViewSerializer.new(
TopicView.new(topic.id, user),
scope: Guardian.new(user),
root: false
root: false,
).as_json
expect(serializer[:topic_field_1]).to eq(true)
@ -40,11 +43,8 @@ describe "custom field extensions" 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
serializer =
TopicListItemSerializer.new(topic, scope: Guardian.new(user), root: false).as_json
expect(serializer[:topic_field_1]).to eq(true)
end
@ -60,11 +60,7 @@ describe "custom field extensions" 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
serializer = PostSerializer.new(post, scope: Guardian.new(user), root: false).as_json
expect(serializer[:post_field_1]).to eq(7)
end
@ -74,7 +70,7 @@ describe "custom field extensions" do
before do
enable_subscription("business")
subscription_custom_field_json['custom_fields'].each do |field_json|
subscription_custom_field_json["custom_fields"].each do |field_json|
custom_field = CustomWizard::CustomField.new(nil, field_json)
custom_field.save
end
@ -90,11 +86,8 @@ describe "custom field extensions" 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
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
@ -110,11 +103,7 @@ describe "custom field extensions" 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
serializer = BasicGroupSerializer.new(group, scope: Guardian.new(user), root: false).as_json
expect(serializer[:group_field_1]).to eq("Hello")
end

Datei anzeigen

@ -1,7 +1,7 @@
# frozen_string_literal: true
describe ::DiscourseTagging, type: :request do
fab!(:user) { Fabricate(:user) }
fab!(:user)
fab!(:tag_1) { Fabricate(:tag, name: "Angus") }
fab!(:tag_2) { Fabricate(:tag, name: "Faizaan") }
fab!(:tag_3) { Fabricate(:tag, name: "Robert") }
@ -16,10 +16,7 @@ describe ::DiscourseTagging, type: :request do
context "for_input is a boolean" do
it "works normally" do
filter_params = {
q: '',
for_input: true
}
filter_params = { q: "", for_input: true }
tags = DiscourseTagging.filter_allowed_tags(guardian, filter_params)
names = tags.map(&:name)
all_tag_names = Tag.all.pluck(:name)
@ -33,15 +30,17 @@ describe ::DiscourseTagging, type: :request do
q: "",
for_input: {
name: "custom-wizard-tag-chooser",
groups: tag_group_1.name
}
groups: tag_group_1.name,
},
}
tags = DiscourseTagging.filter_allowed_tags(guardian, filter_params)
names = tags.map(&:name)
expected_tag_names = TagGroup
expected_tag_names =
TagGroup
.includes(:tags)
.where(id: tag_group_1.id)
.map { |tag_group| tag_group.tags.pluck(:name) }.flatten
.map { |tag_group| tag_group.tags.pluck(:name) }
.flatten
expect(names).to contain_exactly(*expected_tag_names)
end
@ -49,13 +48,7 @@ describe ::DiscourseTagging, type: :request do
context "for_input is an object including an empty tag group string" do
it "returns all tags" do
filter_params = {
q: "",
for_input: {
name: "custom-wizard-tag-chooser",
groups: ""
}
}
filter_params = { q: "", for_input: { name: "custom-wizard-tag-chooser", groups: "" } }
tags = DiscourseTagging.filter_allowed_tags(guardian, filter_params)
names = tags.map(&:name)

Datei anzeigen

@ -6,9 +6,7 @@ describe ExtraLocalesControllerCustomWizard, type: :request do
let(:template) { get_wizard_fixture("wizard") }
let(:permitted) { get_wizard_fixture("wizard/permitted") }
before do
CustomWizard::Template.save(template, skip_jobs: true)
end
before { CustomWizard::Template.save(template, skip_jobs: true) }
before do
js_hash = ExtraLocalesController.bundle_js_hash("wizard")
@ -22,14 +20,14 @@ describe ExtraLocalesControllerCustomWizard, type: :request do
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" }
get @locale_url, headers: { "REFERER" => "/w/super-mega-fun-wizard" }
expect(response.status).to eq(200)
end
it "returns wizard locales when requested by user in a wizard step" do
sign_in(new_user)
get @locale_url, headers: { 'REFERER' => "/w/super-mega-fun-wizard/steps/step_1" }
get @locale_url, headers: { "REFERER" => "/w/super-mega-fun-wizard/steps/step_1" }
expect(response.status).to eq(200)
end
@ -38,7 +36,7 @@ describe ExtraLocalesControllerCustomWizard, type: :request do
CustomWizard::Template.save(template.as_json)
sign_in(new_user)
get @locale_url, headers: { 'REFERER' => "/w/super-mega-fun-wizard" }
get @locale_url, headers: { "REFERER" => "/w/super-mega-fun-wizard" }
expect(response.status).to eq(200)
end

Datei anzeigen

@ -1,40 +1,31 @@
# frozen_string_literal: true
describe ::Guardian do
fab!(:user) {
Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com")
}
fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') }
let(:wizard_template) {
fab!(:user) { Fabricate(:user, name: "Angus", username: "angus", email: "angus@email.com") }
fab!(:category) { Fabricate(:category, name: "cat1", slug: "cat-slug") }
let(:wizard_template) do
JSON.parse(
File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read
File.open("#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json").read,
)
}
end
def create_topic_by_wizard(wizard)
wizard.create_updater(
wizard.steps.first.id,
step_1_field_1: "Topic Title",
step_1_field_2: "topic body"
step_1_field_2: "topic body",
).update
wizard.create_updater(wizard.steps.second.id, {}).update
wizard.create_updater(wizard.steps.last.id,
step_3_field_3: category.id
).update
wizard.create_updater(wizard.steps.last.id, step_3_field_3: category.id).update
topic = Topic.where(
title: "Topic Title",
category_id: category.id
).first
topic = Topic.where(title: "Topic Title", category_id: category.id).first
topic
end
before do
CustomWizard::Template.save(wizard_template, skip_jobs: true)
@template = CustomWizard::Template.find('super_mega_fun_wizard')
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
context "topic created by user using wizard" do
@ -47,11 +38,7 @@ describe ::Guardian do
context "topic created by user without wizard" do
it "restricts editing the topic first post" do
topic_params = {
title: "Topic Title",
raw: "Topic body",
skip_validations: true
}
topic_params = { title: "Topic Title", raw: "Topic body", skip_validations: true }
post = PostCreator.new(user, topic_params).create
expect(user.guardian.wizard_can_edit_topic?(post.topic)).to be_falsey
end

Datei anzeigen

@ -1,16 +1,14 @@
# frozen_string_literal: true
describe InvitesControllerCustomWizard, type: :request do
fab!(:topic) { Fabricate(:topic) }
fab!(:topic)
let(:invite) { Invite.generate(topic.user, email: "angus@mcleod.org", topic: topic) }
let(:template) { get_wizard_fixture("wizard") }
before do
@controller = InvitesController.new
end
before { @controller = InvitesController.new }
it "redirects a user to wizard after invite if after signup is enabled" do
template['after_signup'] = true
template["after_signup"] = true
CustomWizard::Template.save(template, skip_jobs: true)
put "/invites/show/#{invite.invite_key}.json"
expect(cookies[:destination_url]).to eq("/w/super-mega-fun-wizard")

Datei anzeigen

@ -2,42 +2,39 @@
describe Topic, type: :model do
fab!(:category_with_wizard) do
Fabricate(:category, custom_fields: { create_topic_wizard: 'true' })
Fabricate(:category, custom_fields: { create_topic_wizard: "true" })
end
fab!(:category_without_wizard) { Fabricate(:category) }
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
let(:valid_attrs) { Fabricate.attributes_for(:topic) }
context 'with a create_topic_wizard custom field in the category' do
it 'will not allow creating a topic directly' do
context "with a create_topic_wizard custom field in the category" do
it "will not allow creating a topic directly" do
expect do
TopicCreator.create(
user,
Guardian.new(user),
valid_attrs.merge(
title: 'A valid and sufficiently long title for testing',
title: "A valid and sufficiently long title for testing",
category: category_with_wizard.id,
raw: 'hello this is a test topic with category with custom fields'
)
)
end.to raise_error(
Discourse::InvalidParameters,
'Category not allowed for topic creation.'
raw: "hello this is a test topic with category with custom fields",
),
)
end.to raise_error(Discourse::InvalidParameters, "Category not allowed for topic creation.")
end
end
context 'without a create_topic_wizard custom field in the category' do
it 'will allow creating a topic directly' do
context "without a create_topic_wizard custom field in the category" do
it "will allow creating a topic directly" do
expect do
TopicCreator.create(
user,
Guardian.new(user),
valid_attrs.merge(
category: category_without_wizard.id,
title: 'Another valid and sufficiently long title for testing',
raw: 'This is the body of a valid topic'
)
title: "Another valid and sufficiently long title for testing",
raw: "This is the body of a valid topic",
),
)
end.not_to raise_error
end

Datei anzeigen

@ -3,12 +3,10 @@
describe CustomWizardUsersController, type: :request do
let(:template) { get_wizard_fixture("wizard") }
before do
@controller = UsersController.new
end
before { @controller = UsersController.new }
it "redirects a user to wizard after sign up if after signup is enabled" do
template['after_signup'] = true
template["after_signup"] = true
CustomWizard::Template.save(template, skip_jobs: true)
sign_in(Fabricate(:user))
get "/u/account-created"

Datei anzeigen

@ -5,7 +5,8 @@ module DiscourseSubscriptionClient
end
end
SubscriptionClientSupplier = Class.new Object do
SubscriptionClientSupplier =
Class.new Object do
attr_reader :product_slugs
def initialize(product_slugs)
@ -13,10 +14,12 @@ SubscriptionClientSupplier = Class.new Object do
end
end
SubscriptionClientResource = Class.new Object do
SubscriptionClientResource =
Class.new Object do
end
SubscriptionClientSubscription = Class.new Object do
SubscriptionClientSubscription =
Class.new Object do
attr_reader :product_id
def initialize(product_id)
@ -27,10 +30,7 @@ end
module DiscourseSubscriptionClient
class Subscriptions
class Result
attr_accessor :supplier,
:resource,
:subscriptions,
:products
attr_accessor :supplier, :resource, :subscriptions, :products
def any?
supplier.present? && resource.present? && subscriptions.present? && products.present?

Datei anzeigen

@ -16,16 +16,14 @@ describe Jobs::SetAfterTimeWizard do
end
it "sets wizard redirect for all users " do
messages = MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: 'super_mega_fun_wizard')
messages =
MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: "super_mega_fun_wizard")
end
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(
UserCustomField.where(
name: 'redirect_to_wizard',
value: 'super_mega_fun_wizard'
).length
UserCustomField.where(name: "redirect_to_wizard", value: "super_mega_fun_wizard").length,
).to eq(3)
end
@ -37,16 +35,14 @@ describe Jobs::SetAfterTimeWizard do
end
it "only redirects users in the group" do
messages = MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: 'super_mega_fun_wizard')
messages =
MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: "super_mega_fun_wizard")
end
expect(messages.first.data).to eq("super_mega_fun_wizard")
expect(messages.first.user_ids).to match_array([user2.id])
expect(
UserCustomField.where(
name: 'redirect_to_wizard',
value: 'super_mega_fun_wizard'
).length
UserCustomField.where(name: "redirect_to_wizard", value: "super_mega_fun_wizard").length,
).to eq(1)
end
end
@ -58,22 +54,20 @@ describe Jobs::SetAfterTimeWizard do
action: CustomWizard::UserHistory.actions[:step],
actor_id: user1.id,
context: @after_time_template[:id],
subject: step[:id]
subject: step[:id],
)
end
end
it "does not redirect to user" do
messages = MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: 'super_mega_fun_wizard')
messages =
MessageBus.track_publish("/redirect_to_wizard") do
described_class.new.execute(wizard_id: "super_mega_fun_wizard")
end
expect(messages.first.data).to eq("super_mega_fun_wizard")
expect(messages.first.user_ids).to match_array([user2.id, user3.id])
expect(
UserCustomField.where(
name: 'redirect_to_wizard',
value: 'super_mega_fun_wizard'
).length
UserCustomField.where(name: "redirect_to_wizard", value: "super_mega_fun_wizard").length,
).to eq(2)
end
end

Datei anzeigen

@ -2,9 +2,7 @@
def get_wizard_fixture(path)
JSON.parse(
File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/#{path}.json"
).read
File.open("#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/#{path}.json").read,
).with_indifferent_access
end
@ -14,11 +12,7 @@ def enable_subscription(type)
end
def disable_subscriptions
%w[
standard
business
community
].each do |type|
%w[standard business community].each do |type|
CustomWizard::Subscription.stubs("#{type}?".to_sym).returns(false)
CustomWizard::Subscription.any_instance.stubs("#{type}?".to_sym).returns(false)
end

Datei anzeigen

@ -4,9 +4,7 @@ describe CustomWizard::AdminApiController do
fab!(:admin_user) { Fabricate(:user, admin: true) }
let(:api_json) { get_wizard_fixture("api/api") }
before do
sign_in(admin_user)
end
before { sign_in(admin_user) }
it "does not save if user does not have relevant subscription" do
disable_subscriptions

Datei anzeigen

@ -5,7 +5,7 @@ describe CustomWizard::AdminCustomFieldsController do
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
before do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
CustomWizard::CustomField.new(nil, field_json).save
end
sign_in(admin_user)
@ -17,25 +17,19 @@ describe CustomWizard::AdminCustomFieldsController do
end
it "saves custom fields" do
topic_field = CustomWizard::CustomField.find_by_name('topic_field_1')
topic_field = CustomWizard::CustomField.find_by_name("topic_field_1")
topic_field_json = topic_field.as_json
topic_field_json['type'] = 'string'
topic_field_json["type"] = "string"
put "/admin/wizards/custom-fields.json", params: {
custom_field: topic_field_json
}
put "/admin/wizards/custom-fields.json", params: { custom_field: topic_field_json }
expect(response.status).to eq(200)
expect(
CustomWizard::CustomField.find_by_name('topic_field_1').type
).to eq('string')
expect(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]
topic_field = custom_field_json["custom_fields"][0]
delete "/admin/wizards/custom-fields/#{topic_field["name"]}.json"
expect(response.status).to eq(200)
expect(
CustomWizard::CustomField.exists?('topic_field_1')
).to eq(false)
expect(CustomWizard::CustomField.exists?("topic_field_1")).to eq(false)
end
end

Datei anzeigen

@ -5,11 +5,16 @@ describe CustomWizard::AdminLogsController do
let(:template) { get_wizard_fixture("wizard") }
before do
["first", "second", "third"].each_with_index do |key, index|
%w[first second third].each_with_index do |key, index|
temp = template.dup
temp["id"] = "#{key}_test_wizard"
CustomWizard::Template.save(temp, skip_jobs: true)
CustomWizard::Log.create("#{key}_test_wizard", "perform_#{key}_action", "#{key}_test_user", "#{key} log message")
CustomWizard::Log.create(
"#{key}_test_wizard",
"perform_#{key}_action",
"#{key}_test_user",
"#{key} log message",
)
end
sign_in(admin_user)
end
@ -21,21 +26,21 @@ describe CustomWizard::AdminLogsController do
it "returns a list of logs for a wizard" do
get "/admin/wizards/logs/first_test_wizard.json"
expect(response.parsed_body['logs'].length).to eq(1)
expect(response.parsed_body["logs"].length).to eq(1)
end
it "paginates" do
get "/admin/wizards/logs/first_test_wizard.json", params: { page: 1 }
expect(response.parsed_body['logs'].length).to eq(0)
expect(response.parsed_body["logs"].length).to eq(0)
end
it "returns total logs for a wizard" do
get "/admin/wizards/logs/first_test_wizard.json"
expect(response.parsed_body['total']).to eq(1)
expect(response.parsed_body["total"]).to eq(1)
end
it "returns basic wizard" do
get "/admin/wizards/logs/first_test_wizard.json"
expect(response.parsed_body['wizard']['id']).to eq("first_test_wizard")
expect(response.parsed_body["wizard"]["id"]).to eq("first_test_wizard")
end
end

Datei anzeigen

@ -8,27 +8,22 @@ describe CustomWizard::AdminManagerController do
sign_in(admin_user)
template_2 = template.dup
template_2["id"] = 'super_mega_fun_wizard_2'
template_2["id"] = "super_mega_fun_wizard_2"
template_3 = template.dup
template_3["id"] = 'super_mega_fun_wizard_3'
template_3["id"] = "super_mega_fun_wizard_3"
@template_array = [template, template_2, template_3]
FileUtils.mkdir_p(concurrency_safe_tmp_dir) unless Dir.exist?(concurrency_safe_tmp_dir)
@tmp_file_path = File.join(concurrency_safe_tmp_dir, SecureRandom.hex << 'wizards.json')
@tmp_file_path = File.join(concurrency_safe_tmp_dir, 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
it "exports all the wizard templates" do
@template_array.each { |template| CustomWizard::Template.save(template, skip_jobs: true) }
get '/admin/wizards/manager/export.json', params: {
wizard_ids: [
'super_mega_fun_wizard',
'super_mega_fun_wizard_2',
'super_mega_fun_wizard_3'
]
get "/admin/wizards/manager/export.json",
params: {
wizard_ids: %w[super_mega_fun_wizard super_mega_fun_wizard_2 super_mega_fun_wizard_3],
}
expect(response.status).to eq(200)
@ -37,60 +32,60 @@ describe CustomWizard::AdminManagerController do
context "import" do
it "works" do
templates = @template_array.map { |t| t.slice('id', 'name') }
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(response.parsed_body["imported"]).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') }
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)
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(
expect(response.parsed_body["failures"]).to match_array(
@template_array.map do |t|
{
id: t['id'],
messages: I18n.t("wizard.validation.conflict", wizard_id: t['id'])
id: t["id"],
messages: I18n.t("wizard.validation.conflict", wizard_id: t["id"]),
}.as_json
end
end,
)
end
end
it 'destroys wizard templates' do
templates = @template_array.map { |t| t.slice('id', 'name') }
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
@template_array.each { |template| CustomWizard::Template.save(template, skip_jobs: true) }
delete '/admin/wizards/manager/destroy.json', params: {
wizard_ids: [
'super_mega_fun_wizard',
'super_mega_fun_wizard_2',
'super_mega_fun_wizard_3'
]
delete "/admin/wizards/manager/destroy.json",
params: {
wizard_ids: %w[super_mega_fun_wizard super_mega_fun_wizard_2 super_mega_fun_wizard_3],
}
expect(response.status).to eq(200)
expect(response.parsed_body['destroyed']).to match_array(templates)
expect(response.parsed_body["destroyed"]).to match_array(templates)
expect(CustomWizard::Template.list.length).to eq(0)
end
end

Datei anzeigen

@ -9,26 +9,22 @@ describe CustomWizard::SubscriptionController do
end
context "with an admin" do
before do
sign_in(admin_user)
end
before { sign_in(admin_user) }
context "without a subscription" do
before do
disable_subscriptions
end
before { disable_subscriptions }
it "returns the right subscription details" do
get "/admin/wizards/subscription.json"
expect(response.parsed_body["subscribed"]).to eq(false)
expect(response.parsed_body["subscription_attributes"]).to eq(CustomWizard::Subscription.attributes.as_json)
expect(response.parsed_body["subscription_attributes"]).to eq(
CustomWizard::Subscription.attributes.as_json,
)
end
end
context "with a subscription" do
before do
enable_subscription("standard")
end
before { enable_subscription("standard") }
it "returns the right subscription details" do
get "/admin/wizards/subscription.json"

Datei anzeigen

@ -5,18 +5,25 @@ describe CustomWizard::AdminWizardController do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
let(:template) { get_wizard_fixture("wizard") }
let(:category) { Fabricate(:category, custom_fields: { create_topic_wizard: template['name'].parameterize(separator: "_") }) }
let(:category) do
Fabricate(
:category,
custom_fields: {
create_topic_wizard: template["name"].parameterize(separator: "_"),
},
)
end
before do
enable_subscription("standard")
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']
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["id"] = "super_mega_fun_wizard_3"
template_3["after_signup"] = true
CustomWizard::Template.save(template_3, skip_jobs: true)
@ -25,40 +32,51 @@ describe CustomWizard::AdminWizardController do
it "returns a basic list of wizard templates and wizard field types" do
get "/admin/wizards/wizard.json"
expect(
response.parsed_body['wizard_list'].map { |w| w['id'] }
).to match_array(['super_mega_fun_wizard', 'super_mega_fun_wizard_2', 'super_mega_fun_wizard_3'])
expect(
response.parsed_body['field_types'].keys
).to eq(CustomWizard::Field.types.keys.map(&:to_s))
expect(response.parsed_body["wizard_list"].map { |w| w["id"] }).to match_array(
%w[super_mega_fun_wizard super_mega_fun_wizard_2 super_mega_fun_wizard_3],
)
expect(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)
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 whilst making sure create_topic_wizard settings for that wizard are removed from Categories" do
expect(CategoryCustomField.find_by(category_id: category.id, name: 'create_topic_wizard', value: template['name'].parameterize(separator: "_"))).not_to eq(nil)
delete "/admin/wizards/wizard/#{template['id']}.json"
expect(
CategoryCustomField.find_by(
category_id: category.id,
name: "create_topic_wizard",
value: template["name"].parameterize(separator: "_"),
),
).not_to eq(nil)
delete "/admin/wizards/wizard/#{template["id"]}.json"
expect(response.status).to eq(200)
expect(CustomWizard::Template.exists?(template['id'])).to eq(false)
expect(CategoryCustomField.find_by(name: 'create_topic_wizard', value: template['name'].parameterize(separator: "_"))).to eq(nil)
expect(CustomWizard::Template.exists?(template["id"])).to eq(false)
expect(
CategoryCustomField.find_by(
name: "create_topic_wizard",
value: template["name"].parameterize(separator: "_"),
),
).to eq(nil)
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"
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 }
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")
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

Datei anzeigen

@ -1,23 +1,23 @@
# frozen_string_literal: true
describe ApplicationController do
fab!(:user) { Fabricate(:user, username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3]) }
fab!(:user) do
Fabricate(:user, username: "angus", email: "angus@email.com", trust_level: TrustLevel[3])
end
let(:wizard_template) { get_wizard_fixture("wizard") }
let(:permitted_json) { get_wizard_fixture("wizard/permitted") }
before do
CustomWizard::Template.save(wizard_template, skip_jobs: true)
@template = CustomWizard::Template.find('super_mega_fun_wizard')
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
context "with signed in user" do
before do
sign_in(user)
end
before { sign_in(user) }
context "who is required to complete wizard" do
before do
user.custom_fields['redirect_to_wizard'] = 'super_mega_fun_wizard'
user.custom_fields["redirect_to_wizard"] = "super_mega_fun_wizard"
user.save_custom_fields(true)
end
@ -55,10 +55,9 @@ describe ApplicationController do
end
it "saves original destination of user" do
get '/', headers: { 'REFERER' => "/t/2" }
get "/", headers: { "REFERER" => "/t/2" }
expect(
CustomWizard::Wizard.create(@template['id'], user).submissions
.first.redirect_to
CustomWizard::Wizard.create(@template["id"], user).submissions.first.redirect_to,
).to eq("/t/2")
end
end
@ -101,9 +100,7 @@ describe ApplicationController do
end
context "when user is not in permitted group" do
before do
Group.find(13).remove(user)
end
before { Group.find(13).remove(user) }
it "does not redirect user" do
travel_to Time.now + 4.hours
@ -131,7 +128,7 @@ describe ApplicationController do
action: CustomWizard::UserHistory.actions[:step],
actor_id: user.id,
context: @template[:id],
subject: step[:id]
subject: step[:id],
)
end
end

Datei anzeigen

@ -7,10 +7,12 @@ describe "custom field extensions" do
let!(:user) { Fabricate(:user) }
let!(:group) { Fabricate(:group, users: [user]) }
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
let(:subscription_custom_field_json) { get_wizard_fixture("custom_field/subscription_custom_fields") }
let(:subscription_custom_field_json) do
get_wizard_fixture("custom_field/subscription_custom_fields")
end
before do
custom_field_json['custom_fields'].each do |field_json|
custom_field_json["custom_fields"].each do |field_json|
custom_field = CustomWizard::CustomField.new(nil, field_json)
custom_field.save
end
@ -33,13 +35,13 @@ describe "custom field extensions" do
get "/posts/#{post.id}.json"
expect(response.status).to eq(200)
expect(response.parsed_body['post_field_1']).to eq(7)
expect(response.parsed_body["post_field_1"]).to eq(7)
end
context "with a subscription" do
before do
enable_subscription("business")
subscription_custom_field_json['custom_fields'].each do |field_json|
subscription_custom_field_json["custom_fields"].each do |field_json|
custom_field = CustomWizard::CustomField.new(nil, field_json)
custom_field.save
end
@ -63,7 +65,7 @@ describe "custom field extensions" do
get "/groups/#{group.name}.json"
expect(response.status).to eq(200)
expect(response.parsed_body['group']['group_field_1']).to eq("Group cf entry")
expect(response.parsed_body["group"]["group_field_1"]).to eq("Group cf entry")
end
context "preloaded" do
@ -76,7 +78,8 @@ describe "custom field extensions" do
get "/site.json"
expect(response.status).to eq(200)
site_category = response.parsed_body['categories'].select { |c| c['id'] == category.id }.first
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
@ -90,8 +93,8 @@ describe "custom field extensions" do
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")
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

Datei anzeigen

@ -1,16 +1,11 @@
# frozen_string_literal: true
describe CustomWizard::RealtimeValidationsController do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:validation_type) { "test_stub" }
let(:validation_type_stub) {
{
types: [:text],
component: "similar-topics-validator",
backend: true,
required_params: []
}
}
let(:validation_type_stub) do
{ types: [:text], component: "similar-topics-validator", backend: true, required_params: [] }
end
before do
sign_in(user)
@ -24,7 +19,7 @@ describe CustomWizard::RealtimeValidationsController do
def perform(params)
result = CustomWizard::RealtimeValidation::Result.new(:test_stub)
result.items = ["hello", "world"]
result.items = %w[hello world]
result
end
end
@ -40,25 +35,22 @@ describe CustomWizard::RealtimeValidationsController do
it "gives the correct response for a given type" do
CustomWizard::RealtimeValidation.types = { test_stub: validation_type_stub }
get '/realtime-validations.json', params: { type: validation_type }
get "/realtime-validations.json", params: { type: validation_type }
expect(response.status).to eq(200)
expected_response = [
{ "item" => "hello" },
{ "item" => "world" }
]
expected_response = [{ "item" => "hello" }, { "item" => "world" }]
expect(JSON.parse(response.body)).to eq(expected_response)
end
it "gives 400 error when no type is passed" do
CustomWizard::RealtimeValidation.types = { test_stub: validation_type_stub }
get '/realtime-validations.json'
get "/realtime-validations.json"
expect(response.status).to eq(400)
end
it "gives 400 error when a required additional param is missing" do
CustomWizard::RealtimeValidation.types = { test_stub: validation_type_stub }
CustomWizard::RealtimeValidation.types[:test_stub][:required_params] = [:test1]
get '/realtime-validations.json', params: { type: validation_type }
get "/realtime-validations.json", params: { type: validation_type }
expect(response.status).to eq(400)
# the addition is only relevant to this test, so getting rid of it
CustomWizard::RealtimeValidation.types[:test_stub][:required_params] = []
@ -66,7 +58,7 @@ describe CustomWizard::RealtimeValidationsController do
it "gives 500 response code when a non existant type is passed" do
CustomWizard::RealtimeValidation.types = { test_stub: validation_type_stub }
get '/realtime-validations.json', params: { type: "random_type" }
get "/realtime-validations.json", params: { type: "random_type" }
expect(response.status).to eq(500)
end
end

Datei anzeigen

@ -1,8 +1,12 @@
# frozen_string_literal: true
describe CustomWizard::StepsController do
fab!(:user) { Fabricate(:user, username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3]) }
fab!(:user2) { Fabricate(:user, username: 'bob', email: "bob@email.com", trust_level: TrustLevel[2]) }
fab!(:user) do
Fabricate(:user, username: "angus", email: "angus@email.com", trust_level: TrustLevel[3])
end
fab!(:user2) do
Fabricate(:user, username: "bob", email: "bob@email.com", trust_level: TrustLevel[2])
end
let(:wizard_template) { get_wizard_fixture("wizard") }
let(:wizard_field_condition_template) { get_wizard_fixture("condition/wizard_field_condition") }
let(:user_condition_template) { get_wizard_fixture("condition/user_condition") }
@ -11,9 +15,7 @@ describe CustomWizard::StepsController do
let(:route_to_template) { get_wizard_fixture("actions/route_to") }
let(:guests_permitted) { get_wizard_fixture("wizard/guests_permitted") }
before do
CustomWizard::Template.save(wizard_template, skip_jobs: true)
end
before { CustomWizard::Template.save(wizard_template, skip_jobs: true) }
def guest_template
temp = wizard_template.dup
@ -25,10 +27,11 @@ describe CustomWizard::StepsController do
context "with guest" do
it "does not perform a step update" do
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Text input"
}
step_1_field_1: "Text input",
},
}
expect(response.status).to eq(403)
end
@ -40,22 +43,23 @@ describe CustomWizard::StepsController do
end
it "performs a step update" do
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Text input"
}
step_1_field_1: "Text input",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
wizard_id = response.parsed_body['wizard']['id']
wizard_id = response.parsed_body["wizard"]["id"]
wizard = CustomWizard::Wizard.create(wizard_id, nil, cookies[:custom_wizard_guest_id])
expect(wizard.current_submission.fields['step_1_field_1']).to eq("Text input")
expect(wizard.current_submission.fields["step_1_field_1"]).to eq("Text input")
end
context "raises an error" do
it "when the wizard doesnt exist" do
put '/w/not-super-mega-fun-wizard/steps/step_1.json'
put "/w/not-super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(400)
end
@ -65,74 +69,74 @@ describe CustomWizard::StepsController do
new_template["permitted"] = permitted_json["permitted"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(403)
end
it "when the step doesnt exist" do
put '/w/super-mega-fun-wizard/steps/step_10.json'
put "/w/super-mega-fun-wizard/steps/step_10.json"
expect(response.status).to eq(400)
end
end
it "works if the step has no fields" do
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
end
it "returns an updated wizard when condition passes" do
new_template = guest_template.dup
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will pass"
}
step_1_field_1: "Condition will pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
end
it "runs completion actions if guest has completed wizard" do
new_template = guest_template.dup
## route_to action
new_template['actions'].last['run_after'] = 'wizard_completion'
new_template["actions"].last["run_after"] = "wizard_completion"
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put '/w/super-mega-fun-wizard/steps/step_2.json'
put '/w/super-mega-fun-wizard/steps/step_3.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
put "/w/super-mega-fun-wizard/steps/step_2.json"
put "/w/super-mega-fun-wizard/steps/step_3.json"
expect(response.status).to eq(200)
expect(response.parsed_body['redirect_on_complete']).to eq("https://google.com")
expect(response.parsed_body["redirect_on_complete"]).to eq("https://google.com")
end
end
end
context "with user" do
before do
sign_in(user)
end
before { sign_in(user) }
it 'performs a step update' do
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
it "performs a step update" do
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Text input"
}
step_1_field_1: "Text input",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
wizard_id = response.parsed_body['wizard']['id']
wizard_id = response.parsed_body["wizard"]["id"]
wizard = CustomWizard::Wizard.create(wizard_id, user)
expect(wizard.current_submission.fields['step_1_field_1']).to eq("Text input")
expect(wizard.current_submission.fields["step_1_field_1"]).to eq("Text input")
end
context "raises an error" do
it "when the wizard doesnt exist" do
put '/w/not-super-mega-fun-wizard/steps/step_1.json'
put "/w/not-super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(400)
end
@ -142,120 +146,121 @@ describe CustomWizard::StepsController do
new_template["permitted"] = admin_permitted_json["permitted"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(403)
end
it "when the step doesnt exist" do
put '/w/super-mega-fun-wizard/steps/step_10.json'
put "/w/super-mega-fun-wizard/steps/step_10.json"
expect(response.status).to eq(400)
end
end
it "works if the step has no fields" do
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
end
it "returns an updated wizard when condition passes" do
new_template = wizard_template.dup
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will pass"
}
step_1_field_1: "Condition will pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_2")
expect(response.parsed_body["wizard"]["start"]).to eq("step_2")
end
it "runs completion actions if user has completed wizard" do
new_template = wizard_template.dup
## route_to action
new_template['actions'].last['run_after'] = 'wizard_completion'
new_template["actions"].last["run_after"] = "wizard_completion"
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put '/w/super-mega-fun-wizard/steps/step_2.json'
put '/w/super-mega-fun-wizard/steps/step_3.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
put "/w/super-mega-fun-wizard/steps/step_2.json"
put "/w/super-mega-fun-wizard/steps/step_3.json"
expect(response.status).to eq(200)
expect(response.parsed_body['redirect_on_complete']).to eq("https://google.com")
expect(response.parsed_body["redirect_on_complete"]).to eq("https://google.com")
end
it "saves results of completion actions if user has completed wizard" do
new_template = wizard_template.dup
new_template['actions'].first['run_after'] = 'wizard_completion'
new_template["actions"].first["run_after"] = "wizard_completion"
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Topic title",
step_1_field_2: "Topic post"
step_1_field_2: "Topic post",
},
}
}
put '/w/super-mega-fun-wizard/steps/step_2.json'
put '/w/super-mega-fun-wizard/steps/step_3.json'
put "/w/super-mega-fun-wizard/steps/step_2.json"
put "/w/super-mega-fun-wizard/steps/step_3.json"
wizard_id = response.parsed_body['wizard']['id']
wizard_id = response.parsed_body["wizard"]["id"]
wizard = CustomWizard::Wizard.create(wizard_id, user)
topic_id = wizard.submissions.first.fields[new_template['actions'].first['id']]
topic_id = wizard.submissions.first.fields[new_template["actions"].first["id"]]
topic = Topic.find(topic_id)
expect(topic.present?).to eq(true)
end
it "returns a final step without conditions" do
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(false)
expect(response.parsed_body["final"]).to eq(false)
put '/w/super-mega-fun-wizard/steps/step_2.json'
put "/w/super-mega-fun-wizard/steps/step_2.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(false)
expect(response.parsed_body["final"]).to eq(false)
put '/w/super-mega-fun-wizard/steps/step_3.json'
put "/w/super-mega-fun-wizard/steps/step_3.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(true)
expect(response.parsed_body["final"]).to eq(true)
end
context "subscription" do
before do
enable_subscription("standard")
end
before { enable_subscription("standard") }
it "raises an error when user cant see the step due to conditions" do
sign_in(user2)
new_wizard_template = wizard_template.dup
new_wizard_template['steps'][0]['condition'] = user_condition_template['condition']
new_wizard_template["steps"][0]["condition"] = user_condition_template["condition"]
CustomWizard::Template.save(new_wizard_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(403)
end
it "returns an updated wizard when condition doesnt pass" do
new_template = wizard_template.dup
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition wont pass"
}
step_1_field_1: "Condition wont pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_3")
expect(response.parsed_body["wizard"]["start"]).to eq("step_3")
end
it "returns the correct final step when the conditional final step and last step are the same" do
new_template = wizard_template.dup
new_template['steps'][0]['condition'] = user_condition_template['condition']
new_template['steps'][2]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][0]["condition"] = user_condition_template["condition"]
new_template["steps"][2]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
end
@ -263,107 +268,116 @@ describe CustomWizard::StepsController do
sign_in(user2)
new_wizard_template = wizard_template.dup
new_wizard_template['steps'][0]['condition'] = user_condition_template['condition']
new_wizard_template["steps"][0]["condition"] = user_condition_template["condition"]
CustomWizard::Template.save(new_wizard_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json'
put "/w/super-mega-fun-wizard/steps/step_1.json"
expect(response.status).to eq(403)
end
it "returns an updated wizard when condition doesnt pass" do
new_template = wizard_template.dup
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition wont pass"
}
step_1_field_1: "Condition wont pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['wizard']['start']).to eq("step_3")
expect(response.parsed_body["wizard"]["start"]).to eq("step_3")
end
it "returns the correct final step when the conditional final step and last step are the same" do
new_template = wizard_template.dup
new_template['steps'][0]['condition'] = user_condition_template['condition']
new_template['steps'][2]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][0]["condition"] = user_condition_template["condition"]
new_template["steps"][2]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will pass"
}
step_1_field_1: "Condition will pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(false)
expect(response.parsed_body["final"]).to eq(false)
put '/w/super-mega-fun-wizard/steps/step_2.json'
put "/w/super-mega-fun-wizard/steps/step_2.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(false)
expect(response.parsed_body["final"]).to eq(false)
put '/w/super-mega-fun-wizard/steps/step_3.json'
put "/w/super-mega-fun-wizard/steps/step_3.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(true)
expect(response.parsed_body["final"]).to eq(true)
end
it "returns the correct final step when the conditional final step and last step are different" do
new_template = wizard_template.dup
new_template['steps'][2]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][2]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will not pass"
}
step_1_field_1: "Condition will not pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(false)
expect(response.parsed_body["final"]).to eq(false)
put '/w/super-mega-fun-wizard/steps/step_2.json'
put "/w/super-mega-fun-wizard/steps/step_2.json"
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(true)
expect(response.parsed_body["final"]).to eq(true)
end
it "returns the correct final step when the conditional final step is determined in the same action" do
new_template = wizard_template.dup
new_template['steps'][1]['condition'] = wizard_field_condition_template['condition']
new_template['steps'][2]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["condition"] = wizard_field_condition_template["condition"]
new_template["steps"][2]["condition"] = wizard_field_condition_template["condition"]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will not pass"
}
step_1_field_1: "Condition will not pass",
},
}
expect(response.status).to eq(200)
expect(response.parsed_body['final']).to eq(true)
expect(response.parsed_body["final"]).to eq(true)
end
it "excludes the non-included conditional fields from the submissions" do
new_template = wizard_template.dup
new_template['steps'][1]['fields'][0]['condition'] = wizard_field_condition_template['condition']
new_template["steps"][1]["fields"][0]["condition"] = wizard_field_condition_template[
"condition"
]
CustomWizard::Template.save(new_template, skip_jobs: true)
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will pass"
}
step_1_field_1: "Condition will pass",
},
}
put '/w/super-mega-fun-wizard/steps/step_2.json', params: {
put "/w/super-mega-fun-wizard/steps/step_2.json",
params: {
fields: {
step_2_field_1: "1995-04-23"
}
step_2_field_1: "1995-04-23",
},
}
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Condition will not pass"
}
step_1_field_1: "Condition will not pass",
},
}
wizard_id = response.parsed_body['wizard']['id']
wizard_id = response.parsed_body["wizard"]["id"]
wizard = CustomWizard::Wizard.create(wizard_id, user)
submission = wizard.current_submission
expect(submission.fields.keys).not_to include("step_2_field_1")

Datei anzeigen

@ -1,7 +1,9 @@
# frozen_string_literal: true
describe CustomWizard::WizardController do
fab!(:user) { Fabricate(:user, username: 'angus', email: "angus@email.com", trust_level: TrustLevel[3]) }
fab!(:user) do
Fabricate(:user, username: "angus", email: "angus@email.com", trust_level: TrustLevel[3])
end
let(:wizard_template) { get_wizard_fixture("wizard") }
let(:permitted_json) { get_wizard_fixture("wizard/permitted") }
@ -10,66 +12,62 @@ describe CustomWizard::WizardController do
@template = CustomWizard::Template.find("super_mega_fun_wizard")
end
context 'plugin disabled' do
before do
SiteSetting.custom_wizard_enabled = false
end
context "plugin disabled" do
before { SiteSetting.custom_wizard_enabled = false }
it 'redirects to root' do
get '/w/super-mega-fun-wizard', xhr: true
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'
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'
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
context "with user" do
before do
sign_in(user)
end
before { sign_in(user) }
context 'when user skips' do
it 'skips a wizard if user is allowed to skip' do
put '/w/super-mega-fun-wizard/skip.json'
context "when user skips" do
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 'lets user skip if user cant access wizard' do
it "lets user skip if user cant access wizard" do
enable_subscription("standard")
@template["permitted"] = permitted_json["permitted"]
CustomWizard::Template.save(@template, skip_jobs: true)
put '/w/super-mega-fun-wizard/skip.json'
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
it "returns a no skip message if user is not allowed to skip" do
enable_subscription("standard")
@template['required'] = 'true'
@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")
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
it "skip response contains a redirect_to if in users submissions" do
@wizard = CustomWizard::Wizard.create(@template["id"], user)
CustomWizard::Submission.new(@wizard, redirect_to: "/t/2").save
put '/w/super-mega-fun-wizard/skip.json'
expect(response.parsed_body['redirect_to']).to eq('/t/2')
put "/w/super-mega-fun-wizard/skip.json"
expect(response.parsed_body["redirect_to"]).to eq("/t/2")
end
it 'deletes the users redirect_to_wizard if present' do
user.custom_fields['redirect_to_wizard'] = @template["id"]
it "deletes the users redirect_to_wizard if present" do
user.custom_fields["redirect_to_wizard"] = @template["id"]
user.save_custom_fields(true)
@wizard = CustomWizard::Wizard.create(@template["id"], user)
put '/w/super-mega-fun-wizard/skip.json'
put "/w/super-mega-fun-wizard/skip.json"
expect(response.status).to eq(200)
expect(user.reload.redirect_to_wizard).to eq(nil)
end
@ -78,22 +76,25 @@ describe CustomWizard::WizardController do
@wizard = CustomWizard::Wizard.create(@template["id"], user)
CustomWizard::Submission.new(@wizard, step_1_field_1: "Hello World").save
current_submission = @wizard.current_submission
put '/w/super-mega-fun-wizard/skip.json'
put "/w/super-mega-fun-wizard/skip.json"
submissions = CustomWizard::Submission.list(@wizard).submissions
expect(submissions.any? { |submission| submission.id == current_submission.id }).to eq(false)
expect(submissions.any? { |submission| submission.id == current_submission.id }).to eq(
false,
)
end
it "starts from the first step if user visits after skipping the wizard" do
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
put "/w/super-mega-fun-wizard/steps/step_1.json",
params: {
fields: {
step_1_field_1: "Text input"
step_1_field_1: "Text input",
},
}
}
put '/w/super-mega-fun-wizard/skip.json'
get '/w/super-mega-fun-wizard.json'
put "/w/super-mega-fun-wizard/skip.json"
get "/w/super-mega-fun-wizard.json"
expect(response.parsed_body["start"]).to eq('step_1')
expect(response.parsed_body["start"]).to eq("step_1")
end
end
end

Datei anzeigen

@ -1,14 +1,15 @@
# frozen_string_literal: true
describe CustomWizard::BasicWizardSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:template) { get_wizard_fixture("wizard") }
it 'should return basic wizard attributes' do
it "should return basic wizard attributes" do
CustomWizard::Template.save(template, skip_jobs: true)
json = CustomWizard::BasicWizardSerializer.new(
json =
CustomWizard::BasicWizardSerializer.new(
CustomWizard::Builder.new("super_mega_fun_wizard", user).build,
scope: Guardian.new(user)
scope: Guardian.new(user),
).as_json
expect(json[:basic_wizard][:id]).to eq("super_mega_fun_wizard")
expect(json[:basic_wizard][:name]).to eq("Super Mega Fun Wizard")

Datei anzeigen

@ -1,22 +1,23 @@
# frozen_string_literal: true
describe CustomWizard::CustomFieldSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:user)
let(:custom_field_json) { get_wizard_fixture("custom_field/custom_fields") }
it 'should return custom field attributes' do
custom_field_json['custom_fields'].each do |field_json|
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(
json =
CustomWizard::CustomFieldSerializer.new(
CustomWizard::CustomField.find_by_name("topic_field_1"),
scope: Guardian.new(user),
root: false
root: false,
).as_json
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(%w[topic_list_item topic_view])
end
end

Datei anzeigen

@ -1,19 +1,31 @@
# frozen_string_literal: true
describe CustomWizard::LogSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:user)
it 'should return log attributes' do
CustomWizard::Log.create('first-test-wizard', 'perform_first_action', 'first_test_user', 'First log message', 1.day.ago)
CustomWizard::Log.create('second-test-wizard', 'perform_second_action', 'second_test_user', 'Second log message')
it "should return log attributes" do
CustomWizard::Log.create(
"first-test-wizard",
"perform_first_action",
"first_test_user",
"First log message",
1.day.ago,
)
CustomWizard::Log.create(
"second-test-wizard",
"perform_second_action",
"second_test_user",
"Second log message",
)
json_array = ActiveModel::ArraySerializer.new(
json_array =
ActiveModel::ArraySerializer.new(
CustomWizard::Log.list(0).logs,
each_serializer: CustomWizard::LogSerializer
each_serializer: CustomWizard::LogSerializer,
).as_json
expect(json_array.length).to eq(2)
expect(json_array[0][:action]).to eq("perform_second_action")
expect(json_array[0][:username]).to eq('second_test_user')
expect(json_array[0][:username]).to eq("second_test_user")
expect(json_array[0][:message]).to eq("Second log message")
end
end

Datei anzeigen

@ -1,35 +1,41 @@
# frozen_string_literal: true
require_relative '../../plugin_helper'
require_relative "../../plugin_helper"
describe CustomWizard::SubmissionSerializer do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
let(:template_json) {
JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read)
}
let(:template_json) do
JSON.parse(
File.open("#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json").read,
)
end
before do
CustomWizard::Template.save(template_json, skip_jobs: true)
wizard = CustomWizard::Wizard.create(template_json["id"], user1)
CustomWizard::Submission.new(wizard, step_1_field_1: "I am user1 submission", submitted_at: Time.now.iso8601).save
CustomWizard::Submission.new(
wizard,
step_1_field_1: "I am user1 submission",
submitted_at: Time.now.iso8601,
).save
wizard = CustomWizard::Wizard.create(template_json["id"], user2)
CustomWizard::Submission.new(wizard, step_1_field_1: "I am user2 submission", submitted_at: Time.now.iso8601).save
CustomWizard::Submission.new(
wizard,
step_1_field_1: "I am user2 submission",
submitted_at: Time.now.iso8601,
).save
end
it 'should return submission attributes' do
it "should return submission attributes" do
wizard = CustomWizard::Wizard.create(template_json["id"])
list = CustomWizard::Submission.list(wizard, page: 0, order_by: 'id')
list = CustomWizard::Submission.list(wizard, page: 0, order_by: "id")
json_array = ActiveModel::ArraySerializer.new(
list.submissions,
each_serializer: described_class
).as_json
json_array =
ActiveModel::ArraySerializer.new(list.submissions, each_serializer: described_class).as_json
expect(json_array.length).to eq(2)
expect(json_array[0][:id].present?).to eq(true)
@ -40,20 +46,14 @@ describe CustomWizard::SubmissionSerializer do
it "should return field values, types and labels" do
wizard = CustomWizard::Wizard.create(template_json["id"])
list = CustomWizard::Submission.list(wizard, page: 0, order_by: 'id')
list = CustomWizard::Submission.list(wizard, page: 0, order_by: "id")
json_array = ActiveModel::ArraySerializer.new(
list.submissions,
each_serializer: described_class
).as_json
json_array =
ActiveModel::ArraySerializer.new(list.submissions, each_serializer: described_class).as_json
expect(json_array.length).to eq(2)
expect(json_array[0][:fields].as_json).to eq({
"step_1_field_1": {
"value": "I am user2 submission",
"type": "text",
"label": "Text"
}
}.as_json)
expect(json_array[0][:fields].as_json).to eq(
{ step_1_field_1: { value: "I am user2 submission", type: "text", label: "Text" } }.as_json,
)
end
end

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen