0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-09 11:52:54 +01:00
Dieser Commit ist enthalten in:
Angus McLeod 2020-10-20 10:15:03 +11:00
Ursprung 94c56ef550
Commit 8fdd263d8e
16 geänderte Dateien mit 859 neuen und 286 gelöschten Zeilen

Datei anzeigen

@ -113,6 +113,7 @@
wizardFieldSelection=true
userFieldSelection='key,value'
categorySelection='output'
wizardActionSelection='output'
outputDefaultSelection='category'
context='action'
)}}
@ -198,6 +199,7 @@
textSelection='value'
userFieldSelection='key'
wizardFieldSelection='value'
wizardActionSelection='value'
keyDefaultSelection='userField'
context='action'
)}}
@ -270,6 +272,7 @@
textSelection='value,output'
wizardFieldSelection='key,value,assignment'
userFieldSelection='key,value,assignment'
wizardActionSelection=true
groupSelection='value,output'
outputDefaultSelection='group'
context='action'

Datei anzeigen

@ -11,11 +11,11 @@ class CustomWizard::StepsController < ::ApplicationController
permitted[:fields] = params[:fields].select { |k, v| field_ids.include? k }
permitted.permit!
end
wizard = CustomWizard::Builder.new(permitted[:wizard_id].underscore, current_user).build
updater = wizard.create_updater(permitted[:step_id], permitted[:fields])
updater.update
if updater.success?
result = success_json
result.merge!(updater.result) if updater.result

Datei anzeigen

@ -77,6 +77,11 @@ class CustomWizard::Action
multiple: true
).perform
if targets.blank?
log_error("no recipients", "send_message has no recipients")
return
end
targets.each do |target|
if Group.find_by(name: target)
params[:target_group_names] = target
@ -119,12 +124,18 @@ class CustomWizard::Action
def update_profile
params = {}
if (profile_updates = action['profile_updates'])
profile_updates.first[:pairs].each do |pair|
if allowed_profile_field?(pair['key'])
key = cast_profile_key(pair['key'])
value = cast_profile_value(mapper.map_field(pair['value'], pair['value_type']), pair['key'])
value = cast_profile_value(
mapper.map_field(
pair['value'],
pair['value_type']
),
pair['key']
)
if user_field?(pair['key'])
params[:custom_fields] ||= {}
@ -137,10 +148,10 @@ class CustomWizard::Action
end
params = add_custom_fields(params)
if params.present?
result = UserUpdater.new(Discourse.system_user, user).update(params)
if params[:avatar].present?
result = update_avatar(params[:avatar])
end
@ -250,11 +261,11 @@ class CustomWizard::Action
def open_composer
params = basic_topic_params
if params[:title].present? && params[:raw].present?
url = "/new-topic?title=#{params[:title]}"
url += "&body=#{params[:raw]}"
if category_id = action_category
if category_id && category = Category.find(category_id)
url += "&category=#{category.full_slug('/')}"
@ -266,7 +277,7 @@ class CustomWizard::Action
end
route_to = Discourse.base_uri + URI.encode(url)
data['redirect_on_complete'] = route_to
data['route_to'] = route_to
log_info("route: #{route_to}")
else
@ -283,8 +294,15 @@ class CustomWizard::Action
multiple: true
}
).perform
group_map = group_map.flatten.compact
unless group_map.present?
log_error("invalid group map")
return
end
groups = group_map.flatten.reduce([]) do |groups, g|
groups = group_map.reduce([]) do |groups, g|
begin
groups.push(Integer(g))
rescue ArgumentError
@ -324,7 +342,7 @@ class CustomWizard::Action
user: user
).perform
end
if action['code']
data[action['code']] = SecureRandom.hex(8)
url += "&#{action['code']}=#{data[action['code']]}"
@ -336,20 +354,36 @@ class CustomWizard::Action
log_info("route: #{route_to}")
end
def create_group
def create_group
group =
begin
Group.new(new_group_params)
Group.new(new_group_params.except(:usernames, :owner_usernames))
rescue ArgumentError => e
raise Discourse::InvalidParameters, "Invalid group params"
end
if group.save
GroupActionLogger.new(user, group).log_change_group_settings
def get_user_ids(username_string)
User.where(username: username_string.split(",")).pluck(:id)
end
if new_group_params[:owner_usernames].present?
owner_ids = get_user_ids(new_group_params[:owner_usernames])
owner_ids.each { |user_id| group.group_users.build(user_id: user_id, owner: true) }
end
if new_group_params[:usernames].present?
user_ids = get_user_ids(new_group_params[:usernames])
user_ids -= owner_ids if owner_ids
user_ids.each { |user_id| group.group_users.build(user_id: user_id) }
end
GroupActionLogger.new(user, group, skip_guardian: true).log_change_group_settings
log_success("Group created", group.name)
result.output = group.name
else
log_error("Group creation failed")
log_error("Group creation failed", group.errors.messages)
end
end
@ -366,7 +400,7 @@ class CustomWizard::Action
log_success("Category created", category.name)
result.output = category.id
else
log_error("Category creation failed")
log_error("Category creation failed", category.errors.messages)
end
end
@ -378,7 +412,7 @@ class CustomWizard::Action
data: data,
user: user
).perform
if output.is_a?(Array)
output.first
elsif output.is_a?(Integer)
@ -505,10 +539,12 @@ class CustomWizard::Action
user: user
).perform
value = value.parameterize(separator: '_') if attr === "name"
value = value.to_i if attr.include?("_level")
params[attr.to_sym] = value
if value
value = value.parameterize(separator: '_') if attr === "name"
value = value.to_i if attr.include?("_level")
params[attr.to_sym] = value
end
end
end
@ -533,30 +569,36 @@ class CustomWizard::Action
user: user
).perform
if attr === "parent_category_id" && value.is_a?(Array)
value = value[0]
end
if attr === "permissions" && value.is_a?(Array)
permissions = value
value = {}
permissions.each do |p|
k = p[:key]
v = p[:value].to_i
if k.is_a?(Array)
group = Group.find_by(id: k[0])
k = group.name
else
k = k.parameterize(separator: '_')
end
value[k] = v
if value
if attr === "parent_category_id" && value.is_a?(Array)
value = value[0]
end
if attr === "permissions" && value.is_a?(Array)
permissions = value
value = {}
permissions.each do |p|
k = p[:key]
v = p[:value].to_i
if k.is_a?(Array)
group = Group.find_by(id: k[0])
k = group.name
else
k = k.parameterize(separator: '_')
end
value[k] = v
end
end
if attr === 'slug'
value = value.parameterize(separator: '-')
end
params[attr.to_sym] = value
end
params[attr.to_sym] = value
end
end
@ -584,6 +626,8 @@ class CustomWizard::Action
end
def cast_profile_value(value, key)
return value if value.nil?
if profile_url_fields.include?(key)
value['url']
elsif key === 'avatar'

Datei anzeigen

@ -133,7 +133,7 @@ class CustomWizard::Builder
validate_field(field, updater, step_template) if field['type'] != 'text_only'
end
end
next if updater.errors.any?
CustomWizard::Builder.step_handlers.each do |handler|
@ -156,10 +156,10 @@ class CustomWizard::Builder
if @actions.present?
@actions.each do |action|
if (action['run_after'] === updater.step.id) ||
(final_step && (!action['run_after'] || (action['run_after'] === 'wizard_completion')))
CustomWizard::Action.new(
wizard: @wizard,
action: action,
@ -217,7 +217,7 @@ class CustomWizard::Builder
submission = @submissions.last
params[:value] = submission[field_template['id']] if submission[field_template['id']]
end
params[:value] = prefill_field(field_template, step_template) || params[:value]
if field_template['type'] === 'group' && params[:value].present?
@ -339,7 +339,7 @@ class CustomWizard::Builder
if type === 'time' && value.present? && !validate_time(value)
updater.errors.add(id, I18n.t('wizard.field.invalid_time'))
end
CustomWizard::Builder.field_validators.each do |validator|
if type === validator[:type]
validator[:block].call(field, updater, step_template)

Datei anzeigen

@ -48,7 +48,7 @@ class CustomWizard::Mapper
inputs.each do |input|
input_type = input['type']
pairs = input['pairs']
if (input_type === 'conditional' && validate_pairs(pairs)) || input_type === 'assignment'
output = input['output']
output_type = input['output_type']

Datei anzeigen

@ -1,17 +1,27 @@
require 'rails_helper'
describe CustomWizard::Action do
let(:create_topic_action) {{"id":"create_topic","type":"create_topic","title":"text","post":"textarea"}}
let(:send_message_action) {{"id":"send_message","type":"send_message","title":"text","post":"textarea","username":"angus"}}
let(:route_to_action) {{"id":"route_to","type":"route_to","url":"https://google.com"}}
let(:open_composer_action) {{"id":"open_composer","type":"open_composer","title":"text","post":"textarea"}}
let(:add_to_group_action) {{"id":"add_to_group","type":"add_to_group","group_id":"dropdown_groups"}}
fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) }
fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') }
fab!(:group) { Fabricate(:group) }
before do
Group.refresh_automatic_group!(:trust_level_2)
template = JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read)
CustomWizard::Wizard.add_wizard(template)
@wizard = CustomWizard::Wizard.create('super_mega_fun_wizard', user)
end
it 'creates a topic' do
template['steps'][0]['fields'] = [text_field, textarea_field]
template['steps'][0]["actions"] = [create_topic_action]
updater = run_update(template, nil,
text: "Topic Title",
textarea: "topic body"
)
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
updater = built_wizard.create_updater(built_wizard.steps[0].id,
step_1_field_1: "Topic Title",
step_1_field_2: "topic body"
).update
updater2 = built_wizard.create_updater(built_wizard.steps[1].id, {}).update
topic = Topic.where(title: "Topic Title")
expect(topic.exists?).to eq(true)
@ -22,71 +32,102 @@ describe CustomWizard::Action do
end
it 'sends a message' do
fields = [text_field, textarea_field]
User.create(username: 'angus1', email: "angus1@email.com")
if extra_field
fields.push(extra_field)
end
template['steps'][0]['fields'] = fields
template['steps'][0]["actions"] = [send_message_action.merge(extra_action_opts)]
run_update(template, nil,
text: "Message Title",
textarea: "message body"
)
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
built_wizard.create_updater(built_wizard.steps[0].id, {}).update
built_wizard.create_updater(built_wizard.steps[1].id, {}).update
topic = Topic.where(
archetype: Archetype.private_message,
title: "Message Title"
title: "Message title"
)
expect(topic.exists?).to eq(true)
expect(
topic.first.topic_allowed_users.first.user.username
).to eq('angus')
expect(Post.where(
post = Post.where(
topic_id: topic.pluck(:id),
raw: "message body"
).exists?).to eq(true)
raw: "I will interpolate some wizard fields"
)
expect(topic.exists?).to eq(true)
expect(topic.first.topic_allowed_users.first.user.username).to eq('angus1')
expect(post.exists?).to eq(true)
end
it 'updates a profile' do
run_update(template, template['steps'][1]['id'], name: "Sally")
expect(user.name).to eq('Sally')
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
upload = Upload.create!(
url: '/images/image.png',
original_filename: 'image.png',
filesize: 100,
user_id: -1,
)
steps = built_wizard.steps
built_wizard.create_updater(steps[0].id, {}).update
built_wizard.create_updater(steps[1].id,
step_2_field_7: upload.as_json,
).update
expect(user.profile_background_upload.id).to eq(upload.id)
end
it 'opens a composer' do
template['steps'][0]['fields'] = [text_field, textarea_field]
template['steps'][0]["actions"] = [open_composer_action]
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
built_wizard.create_updater(built_wizard.steps[0].id, step_1_field_1: "Text input").update
updater = run_update(template, nil,
text: "Topic Title",
textarea: "topic body"
)
updater = built_wizard.create_updater(built_wizard.steps[1].id, {})
updater.update
expect(updater.result.blank?).to eq(true)
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
category = Category.find_by(id: submissions.first['action_8'])
updater = run_update(template, template['steps'][1]['id'])
expect(updater.result[:redirect_on_complete]).to eq(
"/new-topic?title=Topic%20Title&body=topic%20body"
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@email.com&category=#{category.slug}/#{category.id}&tags=tag1"
)
end
it 'adds a user to a group' do
template['steps'][0]['fields'] = [dropdown_groups_field]
template['steps'][0]["actions"] = [add_to_group_action]
updater = run_update(template, nil, dropdown_groups: group.id)
it 'creates a category' do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
built_wizard.create_updater(built_wizard.steps[0].id, step_1_field_1: "Text input").update
built_wizard.create_updater(built_wizard.steps[1].id, {}).update
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
expect(Category.where(id: submissions.first['action_8']).exists?).to eq(true)
end
it 'creates a group' do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
step_id = built_wizard.steps[0].id
updater = built_wizard.create_updater(step_id, step_1_field_1: "Text input").update
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
expect(Group.where(name: submissions.first['action_9']).exists?).to eq(true)
end
it 'adds a user to a group' do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
step_id = built_wizard.steps[0].id
updater = built_wizard.create_updater(step_id, step_1_field_1: "Text input").update
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
group = Group.find_by(name: submissions.first['action_9'])
expect(group.users.first.username).to eq('angus')
end
it 'watches categories' do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
built_wizard.create_updater(built_wizard.steps[0].id, step_1_field_1: "Text input").update
built_wizard.create_updater(built_wizard.steps[1].id, {}).update
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
expect(CategoryUser.where(
category_id: submissions.first['action_8'],
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(0)
end
it 're-routes a user' do
template['steps'][0]["actions"] = [route_to_action]
updater = run_update(template, nil, {})
expect(updater.result[:redirect_on_next]).to eq(
"https://google.com"
)
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
updater = built_wizard.create_updater(built_wizard.steps.last.id, {})
updater.update
expect(updater.result[:redirect_on_complete]).to eq("https://google.com")
end
end

Datei anzeigen

@ -3,39 +3,19 @@
require 'rails_helper'
describe CustomWizard::Builder do
fab!(:user) { Fabricate(:user, username: 'angus') }
fab!(:trusted_user) { Fabricate(:user, trust_level: 3) }
fab!(:user) { Fabricate(:user, username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) }
fab!(:new_user) { Fabricate(:user, trust_level: 0) }
fab!(:category1) { Fabricate(:category, name: 'cat1') }
fab!(:category2) { Fabricate(:category, name: 'cat2') }
fab!(:group) { Fabricate(:group) }
let!(:template) do
JSON.parse(File.open(
before do
Group.refresh_automatic_group!(:trust_level_2)
template = JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read)
end
def build_wizard(t = template, u = user, build_opts = {}, params = {})
CustomWizard::Wizard.add_wizard(t)
CustomWizard::Builder.new('welcome', u).build(build_opts, params)
end
def add_submission_data(data = {})
PluginStore.set("welcome_submissions", user.id, {
name: 'Angus',
website: 'https://thepavilion.io'
}.merge(data))
end
def get_submission_data
PluginStore.get("welcome_submissions", user.id)
end
def run_update(t = template, step_id = nil, data = {})
wizard = build_wizard(t)
updater = wizard.create_updater(step_id || t['steps'][0]['id'], data)
updater.update
updater
CustomWizard::Wizard.add_wizard(template)
@wizard = CustomWizard::Wizard.create('super_mega_fun_wizard', user)
end
context 'disabled' do
@ -43,15 +23,8 @@ describe CustomWizard::Builder do
SiteSetting.custom_wizard_enabled = false
end
it "returns no steps" do
wizard = build_wizard
expect(wizard.steps.length).to eq(0)
expect(wizard.name).to eq('Welcome')
end
it "doesn't save submissions" do
run_update(template, nil, name: 'Angus')
expect(get_submission_data.blank?).to eq(true)
it "returns nil" do
expect(CustomWizard::Builder.new(@wizard.id, user).build).to eq(nil)
end
end
@ -61,123 +34,164 @@ describe CustomWizard::Builder do
end
it "returns steps" do
expect(build_wizard.steps.length).to eq(2)
expect(
CustomWizard::Builder.new(@wizard.id, user).build.steps.length
).to eq(2)
end
it 'returns no steps if multiple submissions are disabled and user has completed' do
wizard_template = CustomWizard::Wizard.find(@wizard.id)
wizard_template[:multiple_submissions] = false
CustomWizard::Wizard.save(wizard_template)
history_params = {
action: UserHistory.actions[:custom_wizard_step],
acting_user_id: user.id,
context: template['id']
context: @wizard.id
}
UserHistory.create!(history_params.merge(subject: template['steps'][0]['id']))
UserHistory.create!(history_params.merge(subject: template['steps'][1]['id']))
@wizard.steps.each do |step|
UserHistory.create!(history_params.merge(subject: step.id))
end
template["multiple_submissions"] = false
expect(build_wizard(template).steps.length).to eq(0)
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
expect(
CustomWizard::Builder.new(@wizard.id, user).build.steps.length
).to eq(0)
end
it 'returns no steps if user is not permitted' do
template["min_trust"] = 3
expect(build_wizard(template).steps.length).to eq(0)
expect(
CustomWizard::Builder.new(@wizard.id, new_user).build.steps.length
).to eq(0)
end
it 'returns steps if user is permitted' do
template["min_trust"] = 3
expect(build_wizard(template, trusted_user).steps.length).to eq(2)
expect(
CustomWizard::Builder.new(@wizard.id, user).build.steps.length
).to eq(3)
end
it 'returns a wizard with prefilled data if user has partially completed it' do
add_submission_data
wizard = build_wizard
expect(wizard.steps[0].fields.first.value).to eq('Angus')
expect(wizard.steps[1].fields.first.value).to eq('https://thepavilion.io')
expect(
CustomWizard::Builder.new(@wizard.id, user)
.build
.steps[0].fields[0].value
).to eq('I am prefilled')
end
it 'returns a wizard with no prefilled data if options include reset' do
add_submission_data
wizard = build_wizard(template, user, reset: true)
expect(wizard.steps[0].fields.first.value).to eq(nil)
expect(wizard.steps[1].fields.first.value).to eq(nil)
PluginStore.set("super_mega_fun_wizard_submissions", user.id, {
text: 'Input into text',
})
expect(
CustomWizard::Builder.new(@wizard.id, user)
.build(reset: true)
.steps[0].fields[0].value
).to eq(nil)
end
context 'building steps' do
it 'returns step metadata' do
expect(build_wizard.steps[0].title).to eq('Welcome to Pavilion')
expect(build_wizard.steps[1].title).to eq('Tell us about you')
expect(
CustomWizard::Builder.new(@wizard.id, user)
.build(reset: true)
.steps[0]
).to eq('Super Mega Fun Wizard')
end
it 'saves permitted params' do
template['steps'][0]['permitted_params'] = permitted_params
wizard = build_wizard(template, user, {}, param_key: 'param_value')
submissions = get_submission_data
expect(submissions.first['submission_param_key']).to eq('param_value')
@wizard.steps[0].permitted_params = permitted_params
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build({}, param_key: 'param_value')
submissions = PluginStore.get("super_mega_fun_wizard_submissions", user.id)
expect(submissions[0]['submission_param_key']).to eq('param_value')
end
it 'is not permitted if required data is not present' do
template['steps'][0]['required_data'] = required_data
expect(build_wizard(template, user).steps[0].permitted).to eq(false)
@wizard.steps[0].required_data = required_data
expect(
CustomWizard::Builder.new(@wizard.id, user).build.steps[0].permitted
).to eq(false)
end
it 'it shows required data message if required data has message' do
template['steps'][0]['required_data'] = required_data
template['steps'][0]['required_data_message'] = required_data_message
add_submission_data(nickname: "John")
wizard = build_wizard(template, user)
expect(wizard.steps[0].permitted).to eq(false)
expect(wizard.steps[0].permitted_message).to eq(required_data_message)
@wizard.steps[0].required_data = required_data
@wizard.steps[0].required_data_message = "Data is required"
PluginStore.set("super_mega_fun_wizard_submissions", user.id,
text: 'Input into text',
)
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
expect(built_wizard.steps[0].permitted).to eq(false)
expect(built_wizard.steps[0].permitted_message).to eq("Data is required")
end
it 'is permitted if required data is present' do
template['steps'][0]['required_data'] = required_data
PluginStore.set('welcome_submissions', user.id, nickname: "Angus", name: "Angus")
expect(build_wizard(template, user).steps[0].permitted).to eq(true)
@wizard.steps[0].required_data = required_data
PluginStore.set('super_mega_fun_wizard_submissions', user.id,
text: "Input into text"
)
expect(
CustomWizard::Builder.new(@wizard.id, user).build.steps[0].permitted
).to eq(true)
end
it 'returns field metadata' do
expect(build_wizard(template, user).steps[0].fields[0].label).to eq("<p>Name</p>")
expect(build_wizard(template, user).steps[0].fields[0].type).to eq("text")
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
expect(built_wizard.steps[0].fields[0].label).to eq("<p>Name</p>")
expect(built_wizard.steps[0].fields[0].type).to eq("text")
end
it 'returns fields' do
template['steps'][0]['fields'][1] = checkbox_field
expect(build_wizard(template, user).steps[0].fields.length).to eq(2)
@wizard.steps[0].fields[1] = checkbox_field
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
expect(built_wizard.steps[0].fields.length).to eq(2)
end
end
context 'on update' do
it 'saves submissions' do
run_update(template, nil, name: 'Angus')
expect(get_submission_data.first['name']).to eq('Angus')
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
built_wizard.create_updater(built_wizard.steps[0].id,
step_1_field_1: 'Text input'
).update
expect(
PluginStore.get("super_mega_fun_wizard_submissions", user.id)
.first['step_1_field_1']
).to eq('Text input')
end
context 'validation' do
it 'applies min length' do
template['steps'][0]['fields'][0]['min_length'] = 10
updater = run_update(template, nil, name: 'short')
expect(updater.errors.messages[:name].first).to eq(
I18n.t('wizard.field.too_short', label: 'Name', min: 10)
@wizard.steps[0].fields[0].min_length = 10
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
updater = built_wizard.create_updater(built_wizard.steps[0].id,
step_1_field_1: 'Te'
).update
expect(updater.errors.messages[:text].first).to eq(
I18n.t('wizard.field.too_short', label: 'Text', min: 3)
)
end
it 'standardises boolean entries' do
template['steps'][0]['fields'][0] = checkbox_field
run_update(template, nil, checkbox: 'false')
expect(get_submission_data.first['checkbox']).to eq(false)
@wizard.steps[0].fields[0] = checkbox_field
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
updater = built_wizard.create_updater(built_wizard.steps[1].id,
step_2_field_5: 'false'
).update
expect(
PluginStore.get("super_mega_fun_wizard_submissions", user.id)
.first['step_2_field_5']
).to eq(false)
end
it 'requires required fields' do
template['steps'][0]['fields'][0]['required'] = true
expect(run_update(template).errors.messages[:name].first).to eq(
I18n.t('wizard.field.required', label: 'Name')
)
@wizard.steps[0].fields[0]['required'] = true
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
updater = built_wizard.create_updater(built_wizard.steps.second.id).update
expect(
updater.errors.messages[:step_1_field_1].first
).to eq(I18n.t('wizard.field.required', label: 'Text'))
end
end
it 'runs actions attached to a step' do
run_update(template, template['steps'][1]['id'], name: "Gus")
expect(user.name).to eq('Gus')
end
end
end
end

Datei anzeigen

@ -1,14 +0,0 @@
describe CustomWizard::Mapper do
it 'interpolates user data' do
user.name = "Angus"
user.save!
expect(
CustomWizard::Builder.fill_placeholders(
"My name is u{name}",
user,
{}
)
).to eq('My name is Angus')
end

Datei anzeigen

@ -1,49 +1,525 @@
{
"id": "welcome",
"name": "Welcome",
"background": "#006da3",
"id": "super_mega_fun_wizard",
"name": "Super Mega Fun Wizard",
"background": "#333333",
"save_submissions": true,
"multiple_submissions": true,
"after_signup": true,
"min_trust": 1,
"theme_id": 4,
"after_signup": false,
"prompt_completion": true,
"theme_id": 2,
"permitted": [
{
"type": "assignment",
"output_type": "group",
"output_connector": "set",
"output": [
12
]
}
],
"steps": [
{
"id": "welcome",
"title": "Welcome to Pavilion",
"raw_description": "Hey there, thanks for signing up.\n\nWe're Pavilion, an international freelancer cooperative that specialises in online communities.\n\nThis site is our own community, where we work with our clients, users of our open source work and our broader community.\n\n",
"description": "<p>Hey there, thanks for signing up.</p>\n<p>Were Pavilion, an international freelancer cooperative that specialises in online communities.</p>\n<p>This site is our own community, where we work with our clients, users of our open source work and our broader community.</p>",
"id": "step_1",
"title": "Text",
"raw_description": "Text inputs!",
"fields": [
{
"id": "name",
"id": "step_1_field_1",
"label": "Text",
"type": "text",
"label": "Name"
"min_length": "3",
"prefill": [
{
"type": "assignment",
"output": "I am prefilled",
"output_type": "text",
"output_connector": "set"
}
]
},
{
"id": "step_1_field_2",
"label": "Textarea",
"type": "textarea",
"min_length": ""
},
{
"id": "step_1_field_3",
"label": "Composer",
"type": "composer"
},
{
"id": "step_1_field_4",
"label": "I'm only text",
"description": "",
"type": "text_only"
}
],
"description": "<p>Text inputs!</p>"
},
{
"id": "step_2",
"title": "Values",
"raw_description": "Because I couldn't think of another name for this step :)",
"fields": [
{
"id": "step_2_field_1",
"label": "Date",
"type": "date",
"format": "YYYY-MM-DD"
},
{
"id": "step_2_field_2",
"label": "Time",
"type": "time",
"format": "HH:mm"
},
{
"id": "step_2_field_3",
"label": "Date & Time",
"type": "date_time",
"format": ""
},
{
"id": "step_2_field_4",
"label": "Number",
"type": "number"
},
{
"id": "step_2_field_5",
"label": "Checkbox",
"type": "checkbox"
},
{
"id": "step_2_field_7",
"label": "Upload",
"type": "upload",
"file_types": ".jpg,.png"
}
],
"description": "<p>Because I couldnt think of another name for this step <img src=\"/images/emoji/twitter/slight_smile.png?v=9\" title=\":slight_smile:\" class=\"emoji\" alt=\":slight_smile:\"></p>"
},
{
"id": "step_3",
"title": "Combo-boxes",
"raw_description": "Unfortunately not the edible type :sushi: ",
"fields": [
{
"id": "step_3_field_1",
"label": "Custom Dropdown",
"type": "dropdown",
"content": [
{
"type": "association",
"pairs": [
{
"index": 0,
"key": "choice1",
"key_type": "text",
"value": "Choice 1",
"value_type": "text",
"connector": "equal"
},
{
"index": 1,
"key": "choice2",
"key_type": "text",
"value": "Choice 2",
"value_type": "text",
"connector": "association"
},
{
"index": 2,
"key": "choice3",
"key_type": "text",
"value": "Choice 3",
"value_type": "text",
"connector": "association"
}
]
}
]
},
{
"id": "step_3_field_2",
"label": "Tag",
"type": "tag"
},
{
"id": "step_3_field_3",
"label": "Category",
"type": "category",
"limit": 1,
"property": "id"
},
{
"id": "step_3_field_4",
"label": "Group",
"type": "group"
},
{
"id": "step_3_field_5",
"label": "User Selector",
"description": "",
"type": "user_selector"
}
],
"description": "<p>Unfortunately not the edible type <img src=\"/images/emoji/twitter/sushi.png?v=9\" title=\":sushi:\" class=\"emoji\" alt=\":sushi:\"></p>"
}
],
"actions": [
{
"id": "action_9",
"run_after": "step_1",
"type": "create_group",
"title": [
{
"type": "assignment",
"output": "New Group Member",
"output_type": "text",
"output_connector": "set"
}
],
"custom_fields": [
{
"type": "association",
"pairs": [
{
"index": 0,
"key": "group_custom_field",
"key_type": "text",
"value": "step_3_field_1",
"value_type": "wizard_field",
"connector": "association"
}
]
}
],
"name": [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"full_name": [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"usernames": [
{
"type": "assignment",
"output_type": "user",
"output_connector": "set",
"output": [
"angus1"
]
}
],
"owner_usernames": [
{
"type": "assignment",
"output_type": "user",
"output_connector": "set",
"output": [
"angus"
]
}
],
"grant_trust_level": [
{
"type": "assignment",
"output": "3",
"output_type": "text",
"output_connector": "set"
}
],
"mentionable_level": [
{
"type": "assignment",
"output": "1",
"output_type": "text",
"output_connector": "set"
}
],
"messageable_level": [
{
"type": "assignment",
"output": "2",
"output_type": "text",
"output_connector": "set"
}
],
"visibility_level": [
{
"type": "assignment",
"output": "3",
"output_type": "text",
"output_connector": "set"
}
],
"members_visibility_level": [
{
"type": "assignment",
"output": "99",
"output_type": "text",
"output_connector": "set"
}
]
},
{
"id": "about_you",
"title": "Tell us about you",
"raw_description": "We'd like to know a little more about you. Add a your name and your website below. This will update your user profile.",
"description": "<p>Wed like to know a little more about you. Add a your name and your website below. This will update your user profile.</p>",
"fields": [
"id": "action_6",
"run_after": "step_1",
"type": "add_to_group",
"group": [
{
"id": "website",
"label": "Website",
"type": "text"
"type": "assignment",
"output": "action_9",
"output_type": "wizard_action",
"output_connector": "set"
}
],
"actions": [
]
},
{
"id": "action_8",
"run_after": "step_1",
"type": "create_category",
"custom_fields": [
{
"id": "update_profile",
"type": "update_profile",
"profile_updates": [
"type": "association",
"pairs": [
{
"key": "name",
"value": "name"
"index": 0,
"key": "category_custom_field",
"key_type": "text",
"value": "CC Val",
"value_type": "text",
"connector": "association"
}
]
}
],
"name": [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"slug": [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"permissions": [
{
"type": "association",
"pairs": [
{
"index": 0,
"key": "action_9",
"key_type": "wizard_action",
"value": "2",
"value_type": "text",
"connector": "association"
}
]
}
]
},
{
"id": "action_5",
"run_after": "step_1",
"type": "watch_categories",
"notification_level": "tracking",
"wizard_user": true,
"categories": [
{
"type": "assignment",
"output": "action_8",
"output_type": "wizard_action",
"output_connector": "set"
}
],
"mute_remainder": [
{
"type": "assignment",
"output": "true",
"output_type": "text",
"output_connector": "set"
}
]
},
{
"id": "action_1",
"run_after": "step_2",
"type": "create_topic",
"skip_redirect": true,
"post": "step_1_field_2",
"title": [
{
"type": "assignment",
"output": "step_1_field_1",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"category": [
{
"type": "assignment",
"output": "step_3_field_3",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"tags": [
{
"type": "assignment",
"output": "step_3_field_2",
"output_type": "wizard_field",
"output_connector": "set"
}
],
"custom_fields": [
{
"type": "association",
"pairs": [
{
"index": 0,
"key": "custom_field_1",
"key_type": "text",
"value": "title",
"value_type": "user_field",
"connector": "association"
}
]
}
],
"visible": [
{
"type": "conditional",
"output": "true",
"output_type": "text",
"output_connector": "then",
"pairs": [
{
"index": 0,
"key": "name",
"key_type": "user_field",
"value": "Angus",
"value_type": "text",
"connector": "equal"
}
]
}
]
},
{
"id": "action_4",
"run_after": "step_2",
"type": "update_profile",
"profile_updates": [
{
"type": "association",
"pairs": [
{
"index": 0,
"key": "profile_background",
"key_type": "user_field",
"value": "step_2_field_7",
"value_type": "wizard_field",
"connector": "association"
}
]
}
]
},
{
"id": "action_2",
"run_after": "step_2",
"type": "send_message",
"post_builder": true,
"post_template": "I will interpolate some wizard fields w{step_1_field_1} w{step_1_field_2}",
"title": [
{
"type": "assignment",
"output": "Message title",
"output_type": "text",
"output_connector": "set"
}
],
"recipient": [
{
"type": "assignment",
"output_type": "user",
"output_connector": "set",
"output": [
"angus1"
]
}
]
},
{
"id": "action_3",
"run_after": "step_2",
"type": "open_composer",
"post_builder": true,
"post_template": "I am interpolating some user fields u{name} u{username} u{email}",
"title": [
{
"type": "assignment",
"output": "Title of the composer topic",
"output_type": "text",
"output_connector": "set"
}
],
"category": [
{
"type": "assignment",
"output": "action_8",
"output_type": "wizard_action",
"output_connector": "set",
"pairs": [
{
"index": 0,
"key": "step_2_field_5",
"key_type": "wizard_field",
"value": "true",
"value_type": "text",
"connector": "is"
}
]
}
],
"tags": [
{
"type": "assignment",
"output": "tag1",
"output_type": "text",
"output_connector": "set"
}
]
},
{
"id": "action_10",
"run_after": "wizard_completion",
"type": "route_to",
"url": [
{
"type": "assignment",
"output": "https://google.com",
"output_type": "text",
"output_connector": "set"
}
]
}
]

Datei anzeigen

@ -1,49 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe CustomWizardSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:category) { Fabricate(:category) }
let!(:template) do
JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read)
end
let(:category_field) {{"id": "category","type": "category","limit": "1","label": "Category"}}
def build_wizard(t = template, u = user, build_opts = {}, params = {})
CustomWizard::Wizard.add_wizard(t)
CustomWizard::Builder.new('welcome', u).build(build_opts, params)
end
it 'should return the wizard attributes' do
json = CustomWizardSerializer.new(build_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:id]).to eq("welcome")
expect(json[:custom_wizard][:name]).to eq("Welcome")
expect(json[:custom_wizard][:background]).to eq("#006da3")
expect(json[:custom_wizard][:required]).to eq(false)
expect(json[:custom_wizard][:min_trust]).to eq(1)
end
it "should return the wizard user attributes" do
json = CustomWizardSerializer.new(build_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:permitted]).to eq(true)
expect(json[:custom_wizard][:user]).to eq(BasicUserSerializer.new(user, root: false).as_json)
end
it "should not return category attributes if there are no category fields" do
json = CustomWizardSerializer.new(build_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:categories].present?).to eq(false)
expect(json[:custom_wizard][:uncategorized_category_id].present?).to eq(false)
end
it "should return category attributes if there is a category selector field" do
template['steps'][0]['fields'][0] = category_field
json = CustomWizardSerializer.new(build_wizard(template), scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:categories].present?).to eq(true)
expect(json[:custom_wizard][:uncategorized_category_id].present?).to eq(true)
end
end

Datei anzeigen

@ -0,0 +1,13 @@
describe CustomWizard::Mapper do
fab!(:user) { Fabricate(:user, name: 'Angus', username: 'angus', email: "angus@email.com") }
it 'interpolates user data' do
expect(
CustomWizard::Mapper.fill_placeholders(
"My name is u{name}",
user,
{}
)
).to eq('My name is Angus')
end
end

Datei anzeigen

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'rails_helper'
describe CustomWizard::WizardSerializer do
fab!(:user) { Fabricate(:user) }
fab!(:category) { Fabricate(:category) }
before do
template = JSON.parse(File.open(
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
).read)
CustomWizard::Wizard.add_wizard(template)
@wizard = CustomWizard::Wizard.create('super_mega_fun_wizard', user)
end
it 'should return the wizard attributes' do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
json = CustomWizard::WizardSerializer.new(built_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:id]).to eq("super_mega_fun_wizard")
expect(json[:custom_wizard][:name]).to eq("Super Mega Fun Wizard")
expect(json[:custom_wizard][:background]).to eq("#333333")
expect(json[:custom_wizard][:required]).to eq(false)
end
it "should return the wizard user attributes" do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
json = CustomWizard::WizardSerializer.new(built_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:user]).to eq(BasicUserSerializer.new(user, root: false).as_json)
end
it "should not return category attributes if there are no category fields" do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
json = CustomWizard::WizardSerializer.new(built_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:categories].present?).to eq(false)
expect(json[:custom_wizard][:uncategorized_category_id].present?).to eq(false)
end
it "should return category attributes if there is a category selector field" do
built_wizard = CustomWizard::Builder.new(@wizard.id, user).build
json = CustomWizard::WizardSerializer.new(built_wizard, scope: Guardian.new(user)).as_json
expect(json[:custom_wizard][:categories].present?).to eq(true)
expect(json[:custom_wizard][:uncategorized_category_id].present?).to eq(true)
end
end