Add custom field spec and improve custom field structure
Dieser Commit ist enthalten in:
Ursprung
1f1f2c5726
Commit
3da4d546b2
18 geänderte Dateien mit 639 neuen und 96 gelöschten Zeilen
|
@ -2,16 +2,16 @@ import Controller from "@ember/controller";
|
|||
import EmberObject from '@ember/object';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import CustomWizardCustomField from "../models/custom-wizard-custom-field";
|
||||
|
||||
export default Controller.extend({
|
||||
fieldKeys: ['klass', 'type', 'serializers', 'name'],
|
||||
documentationUrl: "https://thepavilion.io/t/3572",
|
||||
|
||||
actions: {
|
||||
addField() {
|
||||
this.get('customFields').pushObject(
|
||||
EmberObject.create({
|
||||
new: true
|
||||
})
|
||||
CustomWizardCustomField.create()
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -21,22 +21,17 @@ export default Controller.extend({
|
|||
|
||||
saveFields() {
|
||||
this.set('saving', true);
|
||||
ajax(`/admin/wizards/custom-fields`, {
|
||||
type: 'PUT',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
custom_fields: this.customFields
|
||||
})
|
||||
}).then(result => {
|
||||
if (result.success) {
|
||||
this.set('saveIcon', 'check');
|
||||
} else {
|
||||
this.set('saveIcon', 'times');
|
||||
}
|
||||
setTimeout(() => this.set('saveIcon', ''), 5000);
|
||||
}).finally(() => this.set('saving', false))
|
||||
.catch(popupAjaxError);
|
||||
CustomWizardCustomField.saveFields(this.customFields)
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
this.set('saveIcon', 'check');
|
||||
} else {
|
||||
this.set('saveIcon', 'times');
|
||||
}
|
||||
setTimeout(() => this.set('saveIcon', ''), 5000);
|
||||
}).finally(() => {
|
||||
this.set('saving', false);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import EmberObject from "@ember/object";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
|
||||
const CustomWizardCustomField = EmberObject.extend({
|
||||
isNew: isEmpty('id')
|
||||
});
|
||||
|
||||
const basePath = '/admin/wizards/custom-fields';
|
||||
|
||||
CustomWizardCustomField.reopenClass({
|
||||
listFields() {
|
||||
return ajax(basePath).catch(popupAjaxError);
|
||||
},
|
||||
|
||||
saveFields(customFields) {
|
||||
return ajax(basePath, {
|
||||
type: 'PUT',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
custom_fields: customFields
|
||||
})
|
||||
}).catch(popupAjaxError);
|
||||
}
|
||||
});
|
||||
|
||||
export default CustomWizardCustomField;
|
|
@ -1,13 +1,14 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import CustomWizardCustomField from "../models/custom-wizard-custom-field";
|
||||
import { A } from "@ember/array";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
model() {
|
||||
return ajax('/admin/wizards/custom-fields');
|
||||
return CustomWizardCustomField.listFields();
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('customFields', A(model || []));
|
||||
const customFields = A(model || []);
|
||||
controller.set('customFields', customFields);
|
||||
}
|
||||
});
|
|
@ -19,6 +19,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{wizard-message
|
||||
key='create'
|
||||
url=documentationUrl
|
||||
component='custom_fields'}}
|
||||
|
||||
<div class="admin-wizard-container">
|
||||
{{#if customFields}}
|
||||
<table>
|
||||
|
|
|
@ -537,6 +537,10 @@
|
|||
}
|
||||
|
||||
.admin-wizards-custom-fields {
|
||||
h3 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.select-kit {
|
||||
width: 200px;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@ en:
|
|||
type: "Select an action type"
|
||||
edit: "You're editing an action"
|
||||
documentation: "Check out the action documentation"
|
||||
custom_fields:
|
||||
create: "Create or edit a custom field record"
|
||||
documentation: Check out the custom field documentation
|
||||
|
||||
editor:
|
||||
show: "Show"
|
||||
|
|
|
@ -6,6 +6,18 @@ en:
|
|||
|
||||
wizard:
|
||||
custom_title: "Wizard"
|
||||
|
||||
custom_field:
|
||||
error:
|
||||
required_attribute: "'%{attr}' is a required attribute"
|
||||
unsupported_class: "'%{class}' is not a supported class"
|
||||
unsupported_serializers: "'%{serializers}' are not supported serializers for '%{class}'"
|
||||
unsupported_type: "%{type} is not a supported custom field type"
|
||||
name_invalid: "'%{name}' is not a valid custom field name"
|
||||
name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})"
|
||||
name_already_taken: "'%{value}' is already taken as a custom field name"
|
||||
save_default: "Failed to save custom field '%{name}'"
|
||||
|
||||
field:
|
||||
too_short: "%{label} must be at least %{min} characters"
|
||||
required: "%{label} is required."
|
||||
|
|
|
@ -4,32 +4,34 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
|
|||
end
|
||||
|
||||
def update
|
||||
custom_fields = custom_field_params[:custom_fields].map do |data|
|
||||
CustomWizard::CustomField.new(data.to_h)
|
||||
fields_to_save = []
|
||||
|
||||
custom_field_params[:custom_fields].each do |field_param|
|
||||
field_id = nil
|
||||
field_data = {}
|
||||
|
||||
if saved_field = CustomWizard::CustomField.find(field_param[:name])
|
||||
CustomWizard::CustomField::ATTRS.each do |attr|
|
||||
field_data[attr] = field_param[attr] || saved_field.send(attr)
|
||||
end
|
||||
field_id = saved_field.id
|
||||
end
|
||||
|
||||
fields_to_save.push(CustomWizard::CustomField.new(field_id, field_data))
|
||||
end
|
||||
|
||||
custom_fields.each do |custom_field|
|
||||
custom_field.validate
|
||||
|
||||
unless custom_field.valid?
|
||||
raise Discourse::InvalidParameters,
|
||||
custom_field.errors.full_messages.join("\n\n")
|
||||
PluginStoreRow.transaction do
|
||||
fields_to_save.each do |field|
|
||||
unless field.save
|
||||
raise ActiveRecord::Rollback.new,
|
||||
field.errors.any? ?
|
||||
field.errors.full_messages.join("\n\n") :
|
||||
I18n.t("wizard.custom_field.error.save_default", name: field.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
all_fields_saved = true
|
||||
|
||||
custom_fields.each do |field|
|
||||
unless field.save
|
||||
all_fields_saved = false
|
||||
end
|
||||
end
|
||||
|
||||
if all_fields_saved
|
||||
render json: success_json
|
||||
else
|
||||
render json: error_json
|
||||
end
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -37,8 +39,8 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
|
|||
def custom_field_params
|
||||
params.permit(
|
||||
custom_fields: [
|
||||
:klass,
|
||||
:name,
|
||||
:klass,
|
||||
:type,
|
||||
serializers: []
|
||||
]
|
||||
|
|
|
@ -1,19 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ::CustomWizard::CustomField
|
||||
include HasErrors
|
||||
include ActiveModel::Serialization
|
||||
|
||||
CLASSES ||= ["topic", "group", "category", "post"]
|
||||
SERIALIZERS ||= ["topic_view", "topic_list_item", "post", "basic_category"]
|
||||
TYPES ||= ["string", "boolean", "integer", "json"]
|
||||
ATTRS ||= ["name", "klass", "type", "serializers"]
|
||||
KEY ||= "custom_wizard_custom_fields"
|
||||
attr_reader :id
|
||||
|
||||
def initialize(data)
|
||||
ATTRS ||= ["name", "klass", "type", "serializers"]
|
||||
REQUIRED ||= ["name", "klass"]
|
||||
NAMESPACE ||= "custom_wizard_custom_fields"
|
||||
NAME_MIN_LENGTH ||= 3
|
||||
|
||||
CLASSES ||= {
|
||||
topic: ["topic_view", "topic_list_item"],
|
||||
group: ["basic_group"],
|
||||
category: ["basic_category"],
|
||||
post: ["post"]
|
||||
}
|
||||
TYPES ||= ["string", "boolean", "integer", "json"]
|
||||
|
||||
def self.serializers
|
||||
CLASSES.values.flatten.uniq
|
||||
end
|
||||
|
||||
def initialize(id, data)
|
||||
@id = id
|
||||
data = data.with_indifferent_access
|
||||
|
||||
ATTRS.each do |attr|
|
||||
self.class.class_eval { attr_accessor attr }
|
||||
send("#{attr}=", data[attr]) if data[attr].present?
|
||||
|
||||
value = data[attr]
|
||||
|
||||
if value.present?
|
||||
send("#{attr}=", value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -22,19 +43,18 @@ class ::CustomWizard::CustomField
|
|||
|
||||
if valid?
|
||||
data = {}
|
||||
name = nil
|
||||
key = name
|
||||
|
||||
ATTRS.each do |attr|
|
||||
value = send(attr)
|
||||
|
||||
if attr == 'name'
|
||||
name = value.parameterize(separator: '_')
|
||||
else
|
||||
data[attr] = value
|
||||
end
|
||||
(ATTRS - ['name']).each do |attr|
|
||||
data[attr] = send(attr)
|
||||
end
|
||||
|
||||
PluginStore.set(KEY, name, data)
|
||||
if self.class.save_to_store(id, key, data)
|
||||
self.class.reset
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
|
@ -43,50 +63,111 @@ class ::CustomWizard::CustomField
|
|||
def validate
|
||||
ATTRS.each do |attr|
|
||||
value = send(attr)
|
||||
i18n_key = "wizard.custom_field.error"
|
||||
|
||||
if value.blank?
|
||||
add_error("Attribute required: #{attr}")
|
||||
if REQUIRED.include?(attr) && value.blank?
|
||||
I18n.t("#{i18n_key}.required_attribute", attr: attr)
|
||||
next
|
||||
end
|
||||
|
||||
if attr == 'klass' && CLASSES.exclude?(value)
|
||||
add_error("Unsupported class: #{value}")
|
||||
if (attr == 'klass' && CLASSES.keys.exclude?(value.to_sym)) ||
|
||||
(attr == 'serializers' && CLASSES[klass.to_sym].blank?)
|
||||
add_error(I18n.t("#{i18n_key}.unsupported_class", class: value))
|
||||
next
|
||||
end
|
||||
|
||||
if attr == 'serializers' && value.present? && (SERIALIZERS & value).empty?
|
||||
add_error("Unsupported serializer: #{value}")
|
||||
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
|
||||
add_error(I18n.t("#{i18n_key}.unsupported_serializers",
|
||||
class: klass,
|
||||
serializers: unsupported.join(", ")
|
||||
))
|
||||
end
|
||||
|
||||
if attr == 'type' && TYPES.exclude?(value)
|
||||
add_error("Unsupported type: #{value}")
|
||||
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
|
||||
end
|
||||
|
||||
if attr == 'name' && value.length < 3
|
||||
add_error("Field name is too short")
|
||||
|
||||
if attr == 'name'
|
||||
unless value.is_a?(String)
|
||||
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
|
||||
end
|
||||
|
||||
if value.length < NAME_MIN_LENGTH
|
||||
add_error(I18n.t("#{i18n_key}.name_too_short", name: value, min_length: NAME_MIN_LENGTH))
|
||||
end
|
||||
|
||||
if new? && self.class.exists?(name)
|
||||
add_error(I18n.t("#{i18n_key}.name_already_taken", name: value))
|
||||
end
|
||||
|
||||
begin
|
||||
@name = value.parameterize(separator: '_')
|
||||
rescue
|
||||
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def new?
|
||||
id.blank?
|
||||
end
|
||||
|
||||
def valid?
|
||||
errors.blank?
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@list = nil
|
||||
end
|
||||
|
||||
def self.list
|
||||
PluginStoreRow.where(plugin_name: KEY)
|
||||
.map do |record|
|
||||
data = JSON.parse(record.value)
|
||||
data[:name] = record.key
|
||||
self.new(data)
|
||||
end
|
||||
@list ||= PluginStoreRow.where(plugin_name: NAMESPACE)
|
||||
.map { |record| create_from_store(record) }
|
||||
end
|
||||
|
||||
def self.list_by(attr, value)
|
||||
self.list.select do |cf|
|
||||
if attr == 'serializers'
|
||||
if attr == :serializers
|
||||
cf.send(attr).include?(value)
|
||||
else
|
||||
cf.send(attr) == value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.exists?(name)
|
||||
PluginStoreRow.where(plugin_name: NAMESPACE, key: name).exists?
|
||||
end
|
||||
|
||||
def self.find(name)
|
||||
records = PluginStoreRow.where(plugin_name: NAMESPACE, key: name)
|
||||
|
||||
if records.exists?
|
||||
create_from_store(records.first)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_from_store(record)
|
||||
data = JSON.parse(record.value)
|
||||
data[:name] = record.key
|
||||
new(record.id, data)
|
||||
end
|
||||
|
||||
def self.save_to_store(id = nil, key, data)
|
||||
if id
|
||||
record = PluginStoreRow.find_by(id: id, plugin_name: NAMESPACE, key: key)
|
||||
return false if !record
|
||||
record.value = data.to_json
|
||||
record.save
|
||||
else
|
||||
record = PluginStoreRow.new(plugin_name: NAMESPACE, key: key)
|
||||
record.type_name = "JSON"
|
||||
record.value = data.to_json
|
||||
record.save
|
||||
end
|
||||
end
|
||||
end
|
41
plugin.rb
41
plugin.rb
|
@ -167,29 +167,44 @@ after_initialize do
|
|||
import_files(DiscoursePluginRegistry.stylesheets["wizard_custom"])
|
||||
end
|
||||
|
||||
CustomWizard::CustomField::CLASSES.each do |klass|
|
||||
add_model_callback(klass.to_sym, :after_initialize) do
|
||||
CustomWizard::CustomField.list_by('klass', klass).each do |field|
|
||||
klass.classify
|
||||
CustomWizard::CustomField::CLASSES.keys.each do |klass|
|
||||
add_model_callback(klass, :after_initialize) do
|
||||
CustomWizard::CustomField.list_by(:klass, klass.to_s).each do |field|
|
||||
klass.to_s
|
||||
.classify
|
||||
.constantize
|
||||
.register_custom_field_type(field.name, field.type.to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CustomWizard::CustomField::SERIALIZERS.each do |serializer_klass|
|
||||
"#{serializer_klass}_serializer".classify.constantize.class_eval do
|
||||
CustomWizard::CustomField.list_by('serializers', serializer_klass).each do |field|
|
||||
attributes(field.name.to_sym)
|
||||
class_eval %{def #{field.name}
|
||||
if "#{serializer_klass}" == "topic_view"
|
||||
object.topic.custom_fields["#{field.name}"]
|
||||
module CustomWizardCustomFieldSerialization
|
||||
def attributes(*args)
|
||||
hash = super
|
||||
@cw_klass = self.class.name.underscore.gsub("_serializer", "")
|
||||
|
||||
if cw_fields.any?
|
||||
cw_fields.each do |field|
|
||||
if @cw_klass == "topic_view"
|
||||
hash[field.name.to_sym] = object.topic.custom_fields["#{field.name}"]
|
||||
else
|
||||
object.custom_fields["#{field.name}"]
|
||||
hash[field.name.to_sym] = object.custom_fields["#{field.name}"]
|
||||
end
|
||||
end}
|
||||
end
|
||||
end
|
||||
|
||||
hash
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cw_fields
|
||||
@cw_fields ||= CustomWizard::CustomField.list_by(:serializers, @cw_klass)
|
||||
end
|
||||
end
|
||||
|
||||
CustomWizard::CustomField.serializers.each do |serializer_klass|
|
||||
"#{serializer_klass}_serializer".classify.constantize.prepend CustomWizardCustomFieldSerialization
|
||||
end
|
||||
|
||||
DiscourseEvent.trigger(:custom_wizard_ready)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
class CustomWizard::CustomFieldSerializer < ApplicationSerializer
|
||||
attributes :klass, :name, :type, :serializers
|
||||
attributes :id, :klass, :name, :type, :serializers
|
||||
end
|
178
spec/components/custom_wizard/custom_field_spec.rb
Normale Datei
178
spec/components/custom_wizard/custom_field_spec.rb
Normale Datei
|
@ -0,0 +1,178 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe CustomWizard::CustomField do
|
||||
|
||||
let(:custom_field_json) {
|
||||
JSON.parse(File.open(
|
||||
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json"
|
||||
).read)
|
||||
}
|
||||
|
||||
it "saves custom field records" do
|
||||
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("
|
||||
plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND
|
||||
key = '#{custom_field.name}' AND
|
||||
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|
|
||||
CustomWizard::CustomField.new(nil, field_json).save
|
||||
end
|
||||
|
||||
updated_field_json = custom_field_json['custom_fields'][0]
|
||||
updated_field_json['serializers'] = ["topic_view"]
|
||||
existing_field = CustomWizard::CustomField.find(updated_field_json["name"])
|
||||
updated_field = CustomWizard::CustomField.new(existing_field.id, updated_field_json)
|
||||
|
||||
expect(updated_field.save).to eq(true)
|
||||
expect(
|
||||
PluginStoreRow.where("
|
||||
plugin_name = '#{CustomWizard::CustomField::NAMESPACE}' AND
|
||||
key = '#{updated_field.name}' AND
|
||||
value::jsonb = '#{updated_field_json.except('name').to_json}'::jsonb
|
||||
", ).exists?
|
||||
).to eq(true)
|
||||
end
|
||||
|
||||
context "validation" do
|
||||
it "does not save with an unsupported class" do
|
||||
invalid_field_json = custom_field_json['custom_fields'].first
|
||||
invalid_field_json['klass'] = 'user'
|
||||
|
||||
custom_field = CustomWizard::CustomField.new(nil, invalid_field_json)
|
||||
|
||||
expect(custom_field.save).to eq(false)
|
||||
expect(custom_field.valid?).to eq(false)
|
||||
expect(custom_field.errors.full_messages.first).to eq(
|
||||
I18n.t("wizard.custom_field.error.unsupported_class", class: "user")
|
||||
)
|
||||
expect(
|
||||
PluginStoreRow.where(
|
||||
plugin_name: CustomWizard::CustomField::NAMESPACE,
|
||||
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'] = 'category'
|
||||
invalid_field_json['serializers'] = ['category', 'site_category']
|
||||
|
||||
custom_field = CustomWizard::CustomField.new(nil, invalid_field_json)
|
||||
|
||||
expect(custom_field.save).to eq(false)
|
||||
expect(custom_field.valid?).to eq(false)
|
||||
expect(custom_field.errors.full_messages.first).to eq(
|
||||
I18n.t("wizard.custom_field.error.unsupported_serializers",
|
||||
class: "category",
|
||||
serializers: "category, site_category"
|
||||
)
|
||||
)
|
||||
expect(
|
||||
PluginStoreRow.where(
|
||||
plugin_name: CustomWizard::CustomField::NAMESPACE,
|
||||
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'
|
||||
|
||||
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")
|
||||
)
|
||||
expect(
|
||||
PluginStoreRow.where(
|
||||
plugin_name: CustomWizard::CustomField::NAMESPACE,
|
||||
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'
|
||||
|
||||
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")
|
||||
)
|
||||
expect(
|
||||
PluginStoreRow.where(
|
||||
plugin_name: CustomWizard::CustomField::NAMESPACE,
|
||||
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|
|
||||
CustomWizard::CustomField.new(nil, field_json).save
|
||||
end
|
||||
|
||||
first_field_json = custom_field_json['custom_fields'][0]
|
||||
custom_field = CustomWizard::CustomField.new(nil, first_field_json)
|
||||
|
||||
expect(custom_field.save).to eq(false)
|
||||
expect(custom_field.valid?).to eq(false)
|
||||
expect(custom_field.errors.full_messages.first).to eq(
|
||||
I18n.t("wizard.custom_field.error.name_already_taken", name: "topic_field_1")
|
||||
)
|
||||
end
|
||||
|
||||
it "does not save with an invalid name" do
|
||||
invalid_field_json = custom_field_json['custom_fields'].first
|
||||
invalid_field_json['name'] = ["invalid_name"]
|
||||
|
||||
custom_field = CustomWizard::CustomField.new(nil, invalid_field_json)
|
||||
|
||||
expect(custom_field.save).to eq(false)
|
||||
expect(custom_field.valid?).to eq(false)
|
||||
expect(custom_field.errors.full_messages.first).to eq(
|
||||
I18n.t("wizard.custom_field.error.name_invalid", name: ["invalid_name"])
|
||||
)
|
||||
expect(
|
||||
PluginStoreRow.where(
|
||||
plugin_name: CustomWizard::CustomField::NAMESPACE,
|
||||
key: custom_field.name
|
||||
).exists?
|
||||
).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "lists" do
|
||||
before do
|
||||
custom_field_json['custom_fields'].each do |field_json|
|
||||
CustomWizard::CustomField.new(nil, field_json).save
|
||||
end
|
||||
end
|
||||
|
||||
it "lists saved custom field records" do
|
||||
expect(CustomWizard::CustomField.list.length).to eq(4)
|
||||
end
|
||||
|
||||
it "lists saved custom field records by attribute value" do
|
||||
expect(CustomWizard::CustomField.list_by(:klass, 'topic').length).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
117
spec/extensions/custom_field_extensions_spec.rb
Normale Datei
117
spec/extensions/custom_field_extensions_spec.rb
Normale Datei
|
@ -0,0 +1,117 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
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) }
|
||||
|
||||
let(:custom_field_json) {
|
||||
JSON.parse(File.open(
|
||||
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json"
|
||||
).read)
|
||||
}
|
||||
|
||||
before do
|
||||
custom_field_json['custom_fields'].each do |field_json|
|
||||
custom_field = CustomWizard::CustomField.new(nil, field_json)
|
||||
custom_field.save
|
||||
end
|
||||
end
|
||||
|
||||
context "topic" do
|
||||
it "registers topic custom fields" do
|
||||
topic
|
||||
expect(Topic.get_custom_field_type("topic_field_1")).to eq(:boolean)
|
||||
end
|
||||
|
||||
it "adds topic custom fields to the topic_view serializer" do
|
||||
topic.custom_fields["topic_field_1"] = true
|
||||
topic.save_custom_fields(true)
|
||||
|
||||
serializer = TopicViewSerializer.new(
|
||||
TopicView.new(topic.id, user),
|
||||
scope: Guardian.new(user),
|
||||
root: false
|
||||
).as_json
|
||||
|
||||
expect(serializer[:topic_field_1]).to eq(true)
|
||||
end
|
||||
|
||||
it "adds topic custom fields to the topic_list_item serializer" do
|
||||
topic.custom_fields["topic_field_1"] = true
|
||||
topic.save_custom_fields(true)
|
||||
|
||||
serializer = TopicListItemSerializer.new(
|
||||
topic,
|
||||
scope: Guardian.new(user),
|
||||
root: false
|
||||
).as_json
|
||||
|
||||
expect(serializer[:topic_field_1]).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "post" do
|
||||
it "registers post custom fields" do
|
||||
post
|
||||
expect(Post.get_custom_field_type("post_field_1")).to eq(:integer)
|
||||
end
|
||||
|
||||
it "adds post custom fields to the post serializer" do
|
||||
post.custom_fields["post_field_1"] = 7
|
||||
post.save_custom_fields(true)
|
||||
|
||||
serializer = PostSerializer.new(
|
||||
post,
|
||||
scope: Guardian.new(user),
|
||||
root: false
|
||||
).as_json
|
||||
|
||||
expect(serializer[:post_field_1]).to eq(7)
|
||||
end
|
||||
end
|
||||
|
||||
context "category" do
|
||||
it "registers category custom fields" do
|
||||
category
|
||||
expect(Category.get_custom_field_type("category_field_1")).to eq(:json)
|
||||
end
|
||||
|
||||
it "adds category custom fields to the basic category serializer" do
|
||||
category.custom_fields["category_field_1"] = { a: 1, b: 2 }.to_json
|
||||
category.save_custom_fields(true)
|
||||
|
||||
serializer = BasicCategorySerializer.new(
|
||||
category,
|
||||
scope: Guardian.new(user),
|
||||
root: false
|
||||
).as_json
|
||||
|
||||
expect(serializer[:category_field_1]).to eq({ a: 1, b: 2 }.to_json)
|
||||
end
|
||||
end
|
||||
|
||||
context "group" do
|
||||
it "registers group custom fields" do
|
||||
group
|
||||
expect(Group.get_custom_field_type("group_field_1")).to eq(:string)
|
||||
end
|
||||
|
||||
it "adds group custom fields to the basic group serializer" do
|
||||
group.custom_fields["group_field_1"] = "Hello"
|
||||
group.save_custom_fields(true)
|
||||
|
||||
serializer = BasicGroupSerializer.new(
|
||||
group,
|
||||
scope: Guardian.new(user),
|
||||
root: false
|
||||
).as_json
|
||||
|
||||
expect(serializer[:group_field_1]).to eq("Hello")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,6 +14,9 @@ describe ExtraLocalesControllerCustomWizard, type: :request do
|
|||
end
|
||||
|
||||
it "returns locales when requested by wizard" do
|
||||
@controller.request = ActionController::TestRequest.create(@controller.class)
|
||||
@controller.request.env['HTTP_REFERER'] = "/w/super-mega-fun-wizard"
|
||||
|
||||
expect(
|
||||
ExtraLocalesController.url("wizard")
|
||||
).to eq(
|
||||
|
|
37
spec/fixtures/custom_field/custom_fields.json
gevendort
Normale Datei
37
spec/fixtures/custom_field/custom_fields.json
gevendort
Normale Datei
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"custom_fields": [
|
||||
{
|
||||
"klass": "topic",
|
||||
"name": "topic_field_1",
|
||||
"type": "boolean",
|
||||
"serializers": [
|
||||
"topic_list_item",
|
||||
"topic_view"
|
||||
]
|
||||
},
|
||||
{
|
||||
"klass": "post",
|
||||
"name": "post_field_1",
|
||||
"type": "integer",
|
||||
"serializers": [
|
||||
"post"
|
||||
]
|
||||
},
|
||||
{
|
||||
"klass": "category",
|
||||
"name": "category_field_1",
|
||||
"type": "json",
|
||||
"serializers": [
|
||||
"basic_category"
|
||||
]
|
||||
},
|
||||
{
|
||||
"klass": "group",
|
||||
"name": "group_field_1",
|
||||
"type": "string",
|
||||
"serializers": [
|
||||
"basic_group"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb
Normale Datei
32
spec/requests/custom_wizard/admin/custom_fields_controller_spec.rb
Normale Datei
|
@ -0,0 +1,32 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe CustomWizard::AdminCustomFieldsController do
|
||||
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
||||
|
||||
let(:custom_field_json) {
|
||||
JSON.parse(File.open(
|
||||
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json"
|
||||
).read)
|
||||
}
|
||||
|
||||
before do
|
||||
custom_field_json['custom_fields'].each do |field_json|
|
||||
CustomWizard::CustomField.new(nil, field_json).save
|
||||
end
|
||||
sign_in(admin_user)
|
||||
end
|
||||
|
||||
it "returns the list of custom fields" do
|
||||
get "/admin/wizards/custom-fields.json"
|
||||
expect(response.parsed_body.length).to eq(4)
|
||||
end
|
||||
|
||||
it "updates the list of custom fields" do
|
||||
custom_field_json['custom_fields'][0]['type'] = 'string'
|
||||
put "/admin/wizards/custom-fields.json", params: custom_field_json
|
||||
expect(response.status).to eq(200)
|
||||
expect(
|
||||
CustomWizard::CustomField.find('topic_field_1').type
|
||||
).to eq('string')
|
||||
end
|
||||
end
|
29
spec/serializers/custom_wizard/custom_field_serializer_spec.rb
Normale Datei
29
spec/serializers/custom_wizard/custom_field_serializer_spec.rb
Normale Datei
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe CustomWizard::CustomFieldSerializer do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
let(:custom_field_json) {
|
||||
JSON.parse(File.open(
|
||||
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/custom_field/custom_fields.json"
|
||||
).read)
|
||||
}
|
||||
|
||||
it 'should return custom field attributes' do
|
||||
custom_field_json['custom_fields'].each do |field_json|
|
||||
CustomWizard::CustomField.new(nil, field_json).save
|
||||
end
|
||||
|
||||
json = CustomWizard::CustomFieldSerializer.new(
|
||||
CustomWizard::CustomField.find("topic_field_1"),
|
||||
scope: Guardian.new(user),
|
||||
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"])
|
||||
end
|
||||
end
|
Laden …
In neuem Issue referenzieren