FEATURE: support to initial values for form templates through /new-topic (#23313)

* FEATURE: adds support for initial values through /new-topic to form templates
This commit is contained in:
Renato Atilio
2023-08-29 18:41:33 -03:00
committed by GitHub
parent 8dddc9eb39
commit 58b49bce41
27 changed files with 178 additions and 45 deletions

View File

@ -4,6 +4,7 @@ export const templateFormFields = [
{ {
type: "checkbox", type: "checkbox",
structure: `- type: checkbox structure: `- type: checkbox
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
attributes: attributes:
label: "${I18n.t("admin.form_templates.field_placeholders.label")}" label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
validations: validations:
@ -12,6 +13,7 @@ export const templateFormFields = [
{ {
type: "input", type: "input",
structure: `- type: input structure: `- type: input
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
attributes: attributes:
label: "${I18n.t("admin.form_templates.field_placeholders.label")}" label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
placeholder: "${I18n.t( placeholder: "${I18n.t(
@ -23,6 +25,7 @@ export const templateFormFields = [
{ {
type: "textarea", type: "textarea",
structure: `- type: textarea structure: `- type: textarea
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
attributes: attributes:
label: "${I18n.t("admin.form_templates.field_placeholders.label")}" label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
placeholder: "${I18n.t( placeholder: "${I18n.t(
@ -34,6 +37,7 @@ export const templateFormFields = [
{ {
type: "dropdown", type: "dropdown",
structure: `- type: dropdown structure: `- type: dropdown
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
choices: choices:
- "${I18n.t("admin.form_templates.field_placeholders.choices.first")}" - "${I18n.t("admin.form_templates.field_placeholders.choices.first")}"
- "${I18n.t("admin.form_templates.field_placeholders.choices.second")}" - "${I18n.t("admin.form_templates.field_placeholders.choices.second")}"
@ -50,6 +54,7 @@ export const templateFormFields = [
{ {
type: "upload", type: "upload",
structure: `- type: upload structure: `- type: upload
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
attributes: attributes:
file_types: ".jpg, .png, .gif" file_types: ".jpg, .png, .gif"
allow_multiple: false allow_multiple: false
@ -60,6 +65,7 @@ export const templateFormFields = [
{ {
type: "multiselect", type: "multiselect",
structure: `- type: multi-select structure: `- type: multi-select
id: ${I18n.t("admin.form_templates.field_placeholders.id")}
choices: choices:
- "${I18n.t("admin.form_templates.field_placeholders.choices.first")}" - "${I18n.t("admin.form_templates.field_placeholders.choices.first")}"
- "${I18n.t("admin.form_templates.field_placeholders.choices.second")}" - "${I18n.t("admin.form_templates.field_placeholders.choices.second")}"

View File

@ -125,6 +125,7 @@
@focusTarget={{this.composer.focusTarget}} @focusTarget={{this.composer.focusTarget}}
@disableTextarea={{this.composer.disableTextarea}} @disableTextarea={{this.composer.disableTextarea}}
@formTemplateIds={{this.composer.formTemplateIds}} @formTemplateIds={{this.composer.formTemplateIds}}
@formTemplateInitialValues={{this.composer.formTemplateInitialValues}}
> >
<div class="composer-fields"> <div class="composer-fields">
<PluginOutlet <PluginOutlet

View File

@ -17,6 +17,7 @@
@onPopupMenuAction={{this.onPopupMenuAction}} @onPopupMenuAction={{this.onPopupMenuAction}}
@popupMenuOptions={{this.popupMenuOptions}} @popupMenuOptions={{this.popupMenuOptions}}
@formTemplateIds={{this.formTemplateIds}} @formTemplateIds={{this.formTemplateIds}}
@formTemplateInitialValues={{@formTemplateInitialValues}}
@replyingToTopic={{this.composer.replyingToTopic}} @replyingToTopic={{this.composer.replyingToTopic}}
@editingPost={{this.composer.editingPost}} @editingPost={{this.composer.editingPost}}
@disabled={{this.disableTextarea}} @disabled={{this.disableTextarea}}

View File

@ -15,7 +15,10 @@
/> />
{{/if}} {{/if}}
<form id="form-template-form"> <form id="form-template-form">
<FormTemplateField::Wrapper @id={{this.selectedFormTemplateId}} /> <FormTemplateField::Wrapper
@id={{this.selectedFormTemplateId}}
@initialValues={{@formTemplateInitialValues}}
/>
</form> </form>
{{else}} {{else}}
<div <div

View File

@ -1,8 +1,9 @@
<div class="control-group form-template-field" data-field-type="checkbox"> <div class="control-group form-template-field" data-field-type="checkbox">
<label class="form-template-field__label"> <label class="form-template-field__label">
<Input <Input
name={{@attributes.label}} name={{@id}}
class="form-template-field__checkbox" class="form-template-field__checkbox"
@checked={{@value}}
@type="checkbox" @type="checkbox"
required={{if @validations.required "required" ""}} required={{if @validations.required "required" ""}}
/> />

View File

@ -11,7 +11,7 @@
{{! TODO(@keegan): Update implementation to use <ComboBox/> instead }} {{! TODO(@keegan): Update implementation to use <ComboBox/> instead }}
{{! Current using <select> as it integrates easily with FormData (will update in v2) }} {{! Current using <select> as it integrates easily with FormData (will update in v2) }}
<select <select
name={{@attributes.label}} name={{@id}}
class="form-template-field__dropdown" class="form-template-field__dropdown"
required={{if @validations.required "required" ""}} required={{if @validations.required "required" ""}}
> >
@ -25,7 +25,7 @@
>{{@attributes.none_label}}</option> >{{@attributes.none_label}}</option>
{{/if}} {{/if}}
{{#each @choices as |choice|}} {{#each @choices as |choice|}}
<option value={{choice}}>{{choice}}</option> <option value={{choice}} selected={{eq @value choice}}>{{choice}}</option>
{{/each}} {{/each}}
</select> </select>
</div> </div>

View File

@ -9,8 +9,9 @@
{{/if}} {{/if}}
<Input <Input
name={{@attributes.label}} name={{@id}}
class="form-template-field__input" class="form-template-field__input"
@value={{@value}}
@type={{if @validations.type @validations.type "text"}} @type={{if @validations.type @validations.type "text"}}
placeholder={{@attributes.placeholder}} placeholder={{@attributes.placeholder}}
required={{if @validations.required "required" ""}} required={{if @validations.required "required" ""}}

View File

@ -11,7 +11,7 @@
{{! TODO(@keegan): Update implementation to use <MultiSelect/> instead }} {{! TODO(@keegan): Update implementation to use <MultiSelect/> instead }}
{{! Current using <select multiple> as it integrates easily with FormData (will update in v2) }} {{! Current using <select multiple> as it integrates easily with FormData (will update in v2) }}
<select <select
name={{@attributes.label}} name={{@id}}
class="form-template-field__multi-select" class="form-template-field__multi-select"
required={{if @validations.required "required" ""}} required={{if @validations.required "required" ""}}
multiple="multiple" multiple="multiple"
@ -25,7 +25,10 @@
>{{@attributes.none_label}}</option> >{{@attributes.none_label}}</option>
{{/if}} {{/if}}
{{#each @choices as |choice|}} {{#each @choices as |choice|}}
<option value={{choice}}>{{choice}}</option> <option
value={{choice}}
selected={{this.isSelected choice}}
>{{choice}}</option>
{{/each}} {{/each}}
</select> </select>
</div> </div>

View File

@ -0,0 +1,9 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
export default class FormTemplateFieldMultiSelect extends Component {
@action
isSelected(option) {
return this.args.value?.includes(option);
}
}

View File

@ -8,7 +8,8 @@
</label> </label>
{{/if}} {{/if}}
<Textarea <Textarea
name={{@attributes.label}} name={{@id}}
@value={{@value}}
class="form-template-field__textarea" class="form-template-field__textarea"
placeholder={{@attributes.placeholder}} placeholder={{@attributes.placeholder}}
pattern={{@validations.pattern}} pattern={{@validations.pattern}}

View File

@ -8,7 +8,7 @@
</label> </label>
{{/if}} {{/if}}
<input type="hidden" name={{@attributes.label}} value={{this.uploadValue}} /> <input type="hidden" name={{@id}} value={{this.uploadValue}} />
<PickFilesButton <PickFilesButton
@fileInputClass="form-template-field__upload" @fileInputClass="form-template-field__upload"

View File

@ -12,12 +12,8 @@ export default class FormTemplateFieldUpload extends Component.extend(
@tracked uploadComplete = false; @tracked uploadComplete = false;
@tracked uploadedFiles = []; @tracked uploadedFiles = [];
@tracked disabled = this.uploading; @tracked disabled = this.uploading;
@tracked @tracked fileUploadElementId = `${dasherize(this.id)}-uploader`;
fileUploadElementId = this.attributes?.label
? `${dasherize(this.attributes.label)}-uploader`
: `${this.elementId}-uploader`;
@tracked fileInputSelector = `#${this.fileUploadElementId}`; @tracked fileInputSelector = `#${this.fileUploadElementId}`;
@tracked id = this.fileUploadElementId;
@computed("uploading", "uploadValue") @computed("uploading", "uploadValue")
get uploadStatus() { get uploadStatus() {

View File

@ -6,9 +6,11 @@
{{#each this.parsedTemplate as |content|}} {{#each this.parsedTemplate as |content|}}
{{component {{component
(concat "form-template-field/" content.type) (concat "form-template-field/" content.type)
id=content.id
attributes=content.attributes attributes=content.attributes
choices=content.choices choices=content.choices
validations=content.validations validations=content.validations
value=(get @initialValues content.id)
}} }}
{{/each}} {{/each}}
</div> </div>

View File

@ -54,6 +54,8 @@ export default class extends DiscourseRoute {
category, category,
tags: transition.to.queryParams.tags, tags: transition.to.queryParams.tags,
}); });
this.composer.set("formTemplateInitialValues", transition.to.queryParams);
}); });
} }

View File

@ -174,6 +174,14 @@ export default class ComposerService extends Service {
return this.model.category?.get("form_template_ids"); return this.model.category?.get("form_template_ids");
} }
get formTemplateInitialValues() {
return this._formTemplateInitialValues;
}
set formTemplateInitialValues(values) {
return this.set("_formTemplateInitialValues", values);
}
@discourseComputed("showPreview") @discourseComputed("showPreview")
toggleText(showPreview) { toggleText(showPreview) {
return showPreview return showPreview
@ -246,7 +254,6 @@ export default class ComposerService extends Service {
canEditTags(canEditTitle, creatingPrivateMessage) { canEditTags(canEditTitle, creatingPrivateMessage) {
const isPrivateMessage = const isPrivateMessage =
creatingPrivateMessage || this.get("model.topic.isPrivateMessage"); creatingPrivateMessage || this.get("model.topic.isPrivateMessage");
return ( return (
canEditTitle && canEditTitle &&
this.site.can_tag_topics && this.site.can_tag_topics &&

View File

@ -2,7 +2,7 @@ import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { render } from "@ember/test-helpers"; import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars"; import { hbs } from "ember-cli-htmlbars";
import { exists } from "discourse/tests/helpers/qunit-helpers"; import { exists, query } from "discourse/tests/helpers/qunit-helpers";
import pretender, { response } from "discourse/tests/helpers/create-pretender"; import pretender, { response } from "discourse/tests/helpers/create-pretender";
module( module(
@ -24,7 +24,12 @@ module(
}); });
test("renders a component based on the component type found in the content YAML", async function (assert) { test("renders a component based on the component type found in the content YAML", async function (assert) {
const content = `- type: checkbox\n- type: input\n- type: textarea\n- type: dropdown\n- type: upload\n- type: multi-select`; const content = `- type: checkbox\n id: checkbox\n
- type: input\n id: name
- type: textarea\n id: notes
- type: dropdown\n id: dropdown
- type: upload\n id: upload
- type: multi-select\n id: multi`;
const componentTypes = [ const componentTypes = [
"checkbox", "checkbox",
"input", "input",
@ -47,6 +52,36 @@ module(
}); });
}); });
test("renders a component based on the component type found in the content YAML, with initial values", async function (assert) {
const content = `- type: checkbox\n id: checkbox\n
- type: input\n id: name
- type: textarea\n id: notes
- type: dropdown\n id: dropdown\n choices:\n - "Option 1"\n - "Option 2"\n - "Option 3"
- type: multi-select\n id: multi\n choices:\n - "Option 1"\n - "Option 2"\n - "Option 3"`;
this.set("content", content);
const initialValues = {
checkbox: "on",
name: "Test Name",
notes: "Test Notes",
dropdown: "Option 1",
multi: ["Option 1"],
};
this.set("initialValues", initialValues);
await render(
hbs`<FormTemplateField::Wrapper @content={{this.content}} @initialValues={{this.initialValues}} />`
);
Object.keys(initialValues).forEach((componentId) => {
assert.equal(
query(`[name='${componentId}']`).value,
initialValues[componentId],
`${componentId} component has initial value`
);
});
});
test("renders a component based on the component type found in the content YAML when passed ids", async function (assert) { test("renders a component based on the component type found in the content YAML when passed ids", async function (assert) {
pretender.get("/form-templates/1.json", () => { pretender.get("/form-templates/1.json", () => {
return response({ return response({

View File

@ -16,6 +16,9 @@ class FormTemplate < ActiveRecord::Base
has_many :category_form_templates, dependent: :destroy has_many :category_form_templates, dependent: :destroy
has_many :categories, through: :category_form_templates has_many :categories, through: :category_form_templates
class NotAllowed < StandardError
end
end end
# == Schema Information # == Schema Information

View File

@ -5750,6 +5750,7 @@ en:
title: "Preview Template" title: "Preview Template"
field_placeholders: field_placeholders:
validations: "enter validations here" validations: "enter validations here"
id: "enter-id-here"
label: "Enter label here" label: "Enter label here"
placeholder: "Enter placeholder here" placeholder: "Enter placeholder here"
none_label: "Select an item" none_label: "Select an item"

View File

@ -5291,3 +5291,6 @@ en:
invalid_yaml: "is not a valid YAML string" invalid_yaml: "is not a valid YAML string"
invalid_type: "contains an invalid template type: %{type} (valid types are: %{valid_types})" invalid_type: "contains an invalid template type: %{type} (valid types are: %{valid_types})"
missing_type: "is missing a field type" missing_type: "is missing a field type"
missing_id: "is missing a field id"
duplicate_ids: "has duplicate ids"
reserved_id: "has a reserved keyword as id: %{id}"

View File

@ -1123,7 +1123,7 @@ posting:
min: 5 min: 5
max: 255 max: 255
max_form_template_content_length: max_form_template_content_length:
default: 2000 default: 5000
max: 150000 max: 150000
email: email:

View File

@ -1,27 +1,30 @@
# frozen_string_literal: true # frozen_string_literal: true
class FormTemplateYamlValidator < ActiveModel::Validator class FormTemplateYamlValidator < ActiveModel::Validator
RESERVED_KEYWORDS = %w[title body category category_id tags]
ALLOWED_TYPES = %w[checkbox dropdown input multi-select textarea upload]
def validate(record) def validate(record)
begin begin
yaml = Psych.safe_load(record.template) yaml = Psych.safe_load(record.template)
check_missing_type(record, yaml) check_missing_fields(record, yaml)
check_allowed_types(record, yaml) check_allowed_types(record, yaml)
check_ids(record, yaml)
rescue Psych::SyntaxError rescue Psych::SyntaxError
record.errors.add(:template, I18n.t("form_templates.errors.invalid_yaml")) record.errors.add(:template, I18n.t("form_templates.errors.invalid_yaml"))
end end
end end
def check_allowed_types(record, yaml) def check_allowed_types(record, yaml)
allowed_types = %w[checkbox dropdown input multi-select textarea upload]
yaml.each do |field| yaml.each do |field|
if !allowed_types.include?(field["type"]) if !ALLOWED_TYPES.include?(field["type"])
return( return(
record.errors.add( record.errors.add(
:template, :template,
I18n.t( I18n.t(
"form_templates.errors.invalid_type", "form_templates.errors.invalid_type",
type: field["type"], type: field["type"],
valid_types: allowed_types.join(", "), valid_types: ALLOWED_TYPES.join(", "),
), ),
) )
) )
@ -29,11 +32,33 @@ class FormTemplateYamlValidator < ActiveModel::Validator
end end
end end
def check_missing_type(record, yaml) def check_missing_fields(record, yaml)
yaml.each do |field| yaml.each do |field|
if field["type"].blank? if field["type"].blank?
return record.errors.add(:template, I18n.t("form_templates.errors.missing_type")) return(record.errors.add(:template, I18n.t("form_templates.errors.missing_type")))
end
if field["id"].blank?
return(record.errors.add(:template, I18n.t("form_templates.errors.missing_id")))
end end
end end
end end
def check_ids(record, yaml)
ids = []
yaml.each do |field|
next if field["id"].blank?
if RESERVED_KEYWORDS.include?(field["id"])
return(
record.errors.add(:template, I18n.t("form_templates.errors.reserved_id", id: field["id"]))
)
end
if ids.include?(field["id"])
return(record.errors.add(:template, I18n.t("form_templates.errors.duplicate_ids")))
end
ids << field["id"]
end
end
end end

View File

@ -2,5 +2,6 @@
Fabricator(:form_template) do Fabricator(:form_template) do
name { sequence(:name) { |i| "template_#{i}" } } name { sequence(:name) { |i| "template_#{i}" } }
template "- type: input" template "- type: input
id: name"
end end

View File

@ -4,11 +4,12 @@ require "rails_helper"
RSpec.describe FormTemplate, type: :model do RSpec.describe FormTemplate, type: :model do
it "can't have duplicate names" do it "can't have duplicate names" do
Fabricate(:form_template, name: "Bug Report", template: "- type: input") Fabricate(:form_template, name: "Bug Report", template: "- type: input\n id: name")
t = Fabricate.build(:form_template, name: "Bug Report", template: "- type: input") t = Fabricate.build(:form_template, name: "Bug Report", template: "- type: input\n id: name")
expect(t.save).to eq(false) expect(t.save).to eq(false)
t = Fabricate.build(:form_template, name: "Bug Report", template: "- type: input") t = Fabricate.build(:form_template, name: "Bug Report", template: "- type: input\n id: name")
expect(t.save).to eq(false) expect(t.save).to eq(false)
expect(t.errors.full_messages.first).to include(I18n.t("errors.messages.taken"))
expect(described_class.count).to eq(1) expect(described_class.count).to eq(1)
end end
@ -16,17 +17,33 @@ RSpec.describe FormTemplate, type: :model do
template = "- type: checkbox\nattributes; bad" template = "- type: checkbox\nattributes; bad"
t = Fabricate.build(:form_template, name: "Feature Request", template: template) t = Fabricate.build(:form_template, name: "Feature Request", template: template)
expect(t.save).to eq(false) expect(t.save).to eq(false)
expect(t.errors.full_messages.first).to include(I18n.t("form_templates.errors.invalid_yaml"))
end end
it "must have a supported type" do it "must have a supported type" do
template = "- type: fancy" template = "- type: fancy\n id: something"
t = Fabricate.build(:form_template, name: "Fancy Template", template: template) t = Fabricate.build(:form_template, name: "Fancy Template", template: template)
expect(t.save).to eq(false) expect(t.save).to eq(false)
expect(t.errors.full_messages.first).to include(
I18n.t(
"form_templates.errors.invalid_type",
type: "fancy",
valid_types: FormTemplateYamlValidator::ALLOWED_TYPES.join(", "),
),
)
end end
it "must have a type property" do it "must have a type property" do
template = "- hello: world" template = "- hello: world\n id: something"
t = Fabricate.build(:form_template, name: "Basic Template", template: template) t = Fabricate.build(:form_template, name: "Basic Template", template: template)
expect(t.save).to eq(false) expect(t.save).to eq(false)
expect(t.errors.full_messages.first).to include(I18n.t("form_templates.errors.missing_type"))
end
it "must have a id property" do
template = "- type: checkbox"
t = Fabricate.build(:form_template, name: "Basic Template", template: template)
expect(t.save).to eq(false)
expect(t.errors.full_messages.first).to include(I18n.t("form_templates.errors.missing_id"))
end end
end end

View File

@ -74,7 +74,7 @@ RSpec.describe Admin::FormTemplatesController do
params: { params: {
name: "Bug Reports", name: "Bug Reports",
template: template:
"- type: input\n attributes:\n label: Website or apps\n description: |\n Which website or app were you using when the bug happened?\n placeholder: |\n e.g. website URL, name of the app\n validations:\n required: true", "- type: input\n id: website\n attributes:\n label: Website or apps\n description: |\n Which website or app were you using when the bug happened?\n placeholder: |\n e.g. website URL, name of the app\n validations:\n required: true",
} }
expect(response.status).to eq(200) expect(response.status).to eq(200)
@ -112,13 +112,13 @@ RSpec.describe Admin::FormTemplatesController do
params: { params: {
id: form_template.id, id: form_template.id,
name: "Updated Template", name: "Updated Template",
template: "- type: checkbox", template: "- type: checkbox\n id: checkbox",
} }
expect(response.status).to eq(200) expect(response.status).to eq(200)
form_template.reload form_template.reload
expect(form_template.name).to eq("Updated Template") expect(form_template.name).to eq("Updated Template")
expect(form_template.template).to eq("- type: checkbox") expect(form_template.template).to eq("- type: checkbox\n id: checkbox")
end end
end end

View File

@ -66,7 +66,7 @@ describe "Admin Customize Form Templates", type: :system do
form_template_page.visit_new form_template_page.visit_new
sample_name = "My First Template" sample_name = "My First Template"
sample_template = "- type: input" sample_template = "- type: input\n id: name"
form_template_page.type_in_template_name(sample_name) form_template_page.type_in_template_name(sample_name)
ace_editor.type_input(sample_template) ace_editor.type_input(sample_template)
@ -101,7 +101,7 @@ describe "Admin Customize Form Templates", type: :system do
it "should show a preview of the template in a modal when clicking the preview button" do it "should show a preview of the template in a modal when clicking the preview button" do
form_template_page.visit_new form_template_page.visit_new
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
ace_editor.type_input("- type: input") ace_editor.type_input("- type: input\n id: name")
form_template_page.click_preview_button form_template_page.click_preview_button
expect(form_template_page).to have_preview_modal expect(form_template_page).to have_preview_modal
@ -112,7 +112,12 @@ describe "Admin Customize Form Templates", type: :system do
form_template_page.visit_new form_template_page.visit_new
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
ace_editor.type_input( ace_editor.type_input(
"- type: input\n- type: textarea\n- type: checkbox\n- type: dropdown\n- type: upload\n- type: multi-select", "- type: input\n id: name
\b\b- type: textarea\n id: description
\b\b- type: checkbox\n id: checkbox
\b\b- type: dropdown\n id: dropdown
\b\b- type: upload\n id: upload
\b\b- type: multi-select\n id: multi-select",
) )
form_template_page.click_preview_button form_template_page.click_preview_button
expect(form_template_page).to have_input_field("input") expect(form_template_page).to have_input_field("input")
@ -127,6 +132,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"checkbox", "checkbox",
'- type: checkbox '- type: checkbox
id: enter-id-here
attributes: attributes:
label: "Enter label here" label: "Enter label here"
validations: validations:
@ -138,6 +144,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"input", "input",
'- type: input '- type: input
id: enter-id-here
attributes: attributes:
label: "Enter label here" label: "Enter label here"
placeholder: "Enter placeholder here" placeholder: "Enter placeholder here"
@ -150,6 +157,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"textarea", "textarea",
'- type: textarea '- type: textarea
id: enter-id-here
attributes: attributes:
label: "Enter label here" label: "Enter label here"
placeholder: "Enter placeholder here" placeholder: "Enter placeholder here"
@ -162,6 +170,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"dropdown", "dropdown",
'- type: dropdown '- type: dropdown
id: enter-id-here
choices: choices:
- "Option 1" - "Option 1"
- "Option 2" - "Option 2"
@ -179,6 +188,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"upload", "upload",
'- type: upload '- type: upload
id: enter-id-here
attributes: attributes:
file_types: ".jpg, .png, .gif" file_types: ".jpg, .png, .gif"
allow_multiple: false allow_multiple: false
@ -192,6 +202,7 @@ describe "Admin Customize Form Templates", type: :system do
quick_insertion_test( quick_insertion_test(
"multiselect", "multiselect",
'- type: multi-select '- type: multi-select
id: enter-id-here
choices: choices:
- "Option 1" - "Option 1"
- "Option 2" - "Option 2"

View File

@ -8,6 +8,7 @@ describe "Composer Form Templates", type: :system do
name: "Bug Reports", name: "Bug Reports",
template: template:
"- type: input "- type: input
id: full-name
attributes: attributes:
label: What is your full name? label: What is your full name?
placeholder: John Doe placeholder: John Doe
@ -16,13 +17,13 @@ describe "Composer Form Templates", type: :system do
) )
end end
fab!(:form_template_2) do fab!(:form_template_2) do
Fabricate(:form_template, name: "Feature Request", template: "- type: checkbox") Fabricate(:form_template, name: "Feature Request", template: "- type: checkbox\n id: check")
end end
fab!(:form_template_3) do fab!(:form_template_3) do
Fabricate(:form_template, name: "Awesome Possum", template: "- type: dropdown") Fabricate(:form_template, name: "Awesome Possum", template: "- type: dropdown\n id: dropdown")
end end
fab!(:form_template_4) do fab!(:form_template_4) do
Fabricate(:form_template, name: "Biography", template: "- type: textarea") Fabricate(:form_template, name: "Biography", template: "- type: textarea\n id: bio")
end end
fab!(:form_template_5) do fab!(:form_template_5) do
Fabricate( Fabricate(
@ -31,12 +32,14 @@ describe "Composer Form Templates", type: :system do
template: template:
%Q( %Q(
- type: input - type: input
id: full-name
attributes: attributes:
label: "What is your name?" label: "What is your name?"
placeholder: "John Smith" placeholder: "John Smith"
validations: validations:
required: false required: false
- type: upload - type: upload
id: prescription
attributes: attributes:
file_types: ".jpg, .png" file_types: ".jpg, .png"
allow_multiple: false allow_multiple: false
@ -44,6 +47,7 @@ describe "Composer Form Templates", type: :system do
validations: validations:
required: true required: true
- type: upload - type: upload
id: additional-docs
attributes: attributes:
file_types: ".jpg, .png, .pdf, .mp3, .mp4" file_types: ".jpg, .png, .pdf, .mp3, .mp4"
allow_multiple: true allow_multiple: true
@ -240,7 +244,7 @@ describe "Composer Form Templates", type: :system do
category_page.visit(category_with_upload_template) category_page.visit(category_with_upload_template)
category_page.new_topic_button.click category_page.new_topic_button.click
attach_file "upload-your-prescription-uploader", attach_file "prescription-uploader",
"#{Rails.root}/spec/fixtures/images/logo.png", "#{Rails.root}/spec/fixtures/images/logo.png",
make_visible: true make_visible: true
composer.fill_title(topic_title) composer.fill_title(topic_title)
@ -253,11 +257,9 @@ describe "Composer Form Templates", type: :system do
end end
it "doesn't allow uploading an invalid file type" do it "doesn't allow uploading an invalid file type" do
topic_title = "Bruce Wayne's Medication"
category_page.visit(category_with_upload_template) category_page.visit(category_with_upload_template)
category_page.new_topic_button.click category_page.new_topic_button.click
attach_file "upload-your-prescription-uploader", attach_file "prescription-uploader",
"#{Rails.root}/spec/fixtures/images/animated.gif", "#{Rails.root}/spec/fixtures/images/animated.gif",
make_visible: true make_visible: true
expect(find("#dialog-holder .dialog-body p", visible: :all)).to have_content( expect(find("#dialog-holder .dialog-body p", visible: :all)).to have_content(
@ -270,10 +272,10 @@ describe "Composer Form Templates", type: :system do
category_page.visit(category_with_upload_template) category_page.visit(category_with_upload_template)
category_page.new_topic_button.click category_page.new_topic_button.click
attach_file "upload-your-prescription-uploader", attach_file "prescription-uploader",
"#{Rails.root}/spec/fixtures/images/logo.png", "#{Rails.root}/spec/fixtures/images/logo.png",
make_visible: true make_visible: true
attach_file "any-additional-docs-uploader", attach_file "additional-docs-uploader",
[ [
"#{Rails.root}/spec/fixtures/media/small.mp3", "#{Rails.root}/spec/fixtures/media/small.mp3",
"#{Rails.root}/spec/fixtures/media/small.mp4", "#{Rails.root}/spec/fixtures/media/small.mp4",

View File

@ -8,6 +8,7 @@ describe "Composer Form Template Validations", type: :system, js: true do
name: "Bug Reports", name: "Bug Reports",
template: template:
"- type: input "- type: input
id: full-name
attributes: attributes:
label: What is your full name? label: What is your full name?
placeholder: John Doe placeholder: John Doe
@ -24,6 +25,7 @@ describe "Composer Form Template Validations", type: :system, js: true do
name: "Websites", name: "Websites",
template: template:
"- type: input "- type: input
id: website-name
attributes: attributes:
label: What is your website name? label: What is your website name?
placeholder: https://www.example.com placeholder: https://www.example.com