Wizard: Server Side Validation + Finished Step
This commit is contained in:
parent
be1d74d207
commit
9f12b571ef
|
@ -64,10 +64,11 @@ export default Ember.Component.extend({
|
|||
}
|
||||
|
||||
const $elem = this.$();
|
||||
const minimumResultsForSearch = this.capabilities.isIOS ? -1 : 5;
|
||||
const caps = this.capabilities;
|
||||
const minimumResultsForSearch = (caps && caps.isIOS) ? -1 : 5;
|
||||
$elem.select2({
|
||||
formatResult: this.comboTemplate, minimumResultsForSearch,
|
||||
width: 'resolve',
|
||||
width: this.get('width') || 'resolve',
|
||||
allowClear: true
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { htmlHelper } from 'discourse-common/lib/helpers';
|
||||
|
||||
export default htmlHelper((key, params) => I18n.t(key, params.hash));
|
|
@ -1,4 +1,4 @@
|
|||
import ComboboxView from 'discourse/components/combo-box';
|
||||
import ComboboxView from 'discourse-common/components/combo-box';
|
||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { observes, on } from 'ember-addons/ember-computed-decorators';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { iconHTML } from 'discourse-common/helpers/fa-icon';
|
||||
import Combobox from 'discourse/components/combo-box';
|
||||
import Combobox from 'discourse-common/components/combo-box';
|
||||
import { on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Combobox.extend({
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//= require env
|
||||
//= require jquery_include
|
||||
//= require ember_include
|
||||
//= require loader
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
//= require ./discourse/views/container
|
||||
//= require ./discourse/views/modal-body
|
||||
//= require ./discourse/views/flag
|
||||
//= require ./discourse/components/combo-box
|
||||
//= require ./discourse/components/edit-category-panel
|
||||
//= require ./discourse/views/button
|
||||
//= require ./discourse/components/dropdown-button
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//= require logster
|
||||
//= require ./env
|
||||
//= require ./discourse-objects
|
||||
//= require probes.js
|
||||
|
||||
|
@ -38,4 +37,3 @@
|
|||
//= require virtual-dom
|
||||
//= require virtual-dom-amd
|
||||
//= require highlight.js
|
||||
//= require_tree ./discourse/ember
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
//= require env
|
||||
//= require template_include.js
|
||||
//= require select2.js
|
||||
|
|
|
@ -4,5 +4,8 @@ export default Ember.Component.extend({
|
|||
classNameBindings: [':wizard-field', ':text-field', 'field.invalid'],
|
||||
|
||||
@computed('field.id')
|
||||
inputClassName: id => `field-${Ember.String.dasherize(id)}`
|
||||
inputClassName: id => `field-${Ember.String.dasherize(id)}`,
|
||||
|
||||
@computed('field.type')
|
||||
inputComponentName: type => `wizard-field-${type}`
|
||||
});
|
||||
|
|
|
@ -12,6 +12,9 @@ export default Ember.Component.extend({
|
|||
@computed('step.displayIndex', 'wizard.totalSteps')
|
||||
showNextButton: (current, total) => current < total,
|
||||
|
||||
@computed('step.displayIndex', 'wizard.totalSteps')
|
||||
showDoneButton: (current, total) => current === total,
|
||||
|
||||
@computed('step.index')
|
||||
showBackButton: index => index > 0,
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ export const States = {
|
|||
|
||||
export default {
|
||||
_validState: null,
|
||||
errorDescription: null,
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
@ -23,8 +24,14 @@ export default {
|
|||
@computed('_validState')
|
||||
unchecked: state => state === States.UNCHECKED,
|
||||
|
||||
setValid(valid) {
|
||||
setValid(valid, description) {
|
||||
this.set('_validState', valid ? States.VALID : States.INVALID);
|
||||
|
||||
if (!valid && description && description.length) {
|
||||
this.set('errorDescription', description);
|
||||
} else {
|
||||
this.set('errorDescription', null);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
export default Ember.Route.extend({
|
||||
model(params) {
|
||||
const allSteps = this.modelFor('application').steps;
|
||||
return allSteps.findProperty('id', params.step_id);
|
||||
const step = allSteps.findProperty('id', params.step_id);
|
||||
return step ? step : allSteps[0];
|
||||
},
|
||||
|
||||
setupController(controller, step) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{{combo-box value=field.value content=field.options nameProperty="label" width="400px"}}
|
|
@ -0,0 +1 @@
|
|||
{{input value=field.value class=inputClassName placeholder=field.placeholder}}
|
|
@ -2,6 +2,14 @@
|
|||
<span class='label-value'>{{field.label}}</span>
|
||||
|
||||
<div class='input-area'>
|
||||
{{input value=field.value class=inputClassName placeholder=field.placeholder}}
|
||||
{{component inputComponentName field=field inputClassName=inputClassName}}
|
||||
</div>
|
||||
|
||||
{{#if field.errorDescription}}
|
||||
<div class='field-error-description'>{{field.errorDescription}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if field.description}}
|
||||
<div class='field-description'>{{field.description}}</div>
|
||||
{{/if}}
|
||||
</label>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{/if}}
|
||||
|
||||
{{#if step.description}}
|
||||
<p class='wizard-step-description'>{{step.description}}</p>
|
||||
<p class='wizard-step-description'>{{{step.description}}}</p>
|
||||
{{/if}}
|
||||
|
||||
{{#wizard-step-form step=step}}
|
||||
|
@ -14,24 +14,33 @@
|
|||
|
||||
<div class='wizard-step-footer'>
|
||||
<div class='wizard-progress'>
|
||||
<div class='text'>{{i18n "wizard.step" current=step.displayIndex total=wizard.totalSteps}}</div>
|
||||
<div class='text'>{{bound-i18n "wizard.step" current=step.displayIndex total=wizard.totalSteps}}</div>
|
||||
<div class='bar-container'>
|
||||
<div class='bar-contents' style={{barStyle}}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if showBackButton}}
|
||||
<button class='wizard-btn back' {{action "backStep"}} disabled={{saving}}>
|
||||
{{fa-icon "chevron-left"}}
|
||||
{{i18n "wizard.back"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
<div class='wizard-buttons'>
|
||||
{{#if showBackButton}}
|
||||
<button class='wizard-btn back' {{action "backStep"}} disabled={{saving}}>
|
||||
{{fa-icon "chevron-left"}}
|
||||
{{i18n "wizard.back"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if showNextButton}}
|
||||
<button class='wizard-btn next' {{action "nextStep"}} disabled={{saving}}>
|
||||
{{i18n "wizard.next"}}
|
||||
{{fa-icon "chevron-right"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
{{#if showNextButton}}
|
||||
<button class='wizard-btn next' {{action "nextStep"}} disabled={{saving}}>
|
||||
{{i18n "wizard.next"}}
|
||||
{{fa-icon "chevron-right"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if showDoneButton}}
|
||||
<button class='wizard-btn done' {{action "finished"}} disabled={{saving}}>
|
||||
{{fa-icon "check"}}
|
||||
{{i18n "wizard.done"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,9 @@ test("Forum Name Step", assert => {
|
|||
assert.ok(exists('.wizard-step-title'));
|
||||
assert.ok(exists('.wizard-step-description'));
|
||||
assert.ok(!exists('.invalid .field-full-name'), "don't show it as invalid until the user does something");
|
||||
assert.ok(exists('.wizard-field .field-description'));
|
||||
assert.ok(!exists('.wizard-btn.back'));
|
||||
assert.ok(!exists('.wizard-field .field-error-description'));
|
||||
});
|
||||
|
||||
// invalid data
|
||||
|
@ -32,16 +34,19 @@ test("Forum Name Step", assert => {
|
|||
click('.wizard-btn.next');
|
||||
andThen(() => {
|
||||
assert.ok(exists('.invalid .field-full-name'));
|
||||
assert.ok(exists('.wizard-field .field-error-description'));
|
||||
});
|
||||
|
||||
// server validation ok
|
||||
fillIn('input.field-full-name', "Evil Trout");
|
||||
click('.wizard-btn.next');
|
||||
andThen(() => {
|
||||
assert.ok(!exists('.wizard-field .field-error-description'));
|
||||
assert.ok(!exists('.wizard-step-title'));
|
||||
assert.ok(!exists('.wizard-step-description'));
|
||||
assert.ok(exists('input.field-email'), "went to the next step");
|
||||
assert.ok(!exists('.wizard-btn.next'));
|
||||
assert.ok(exists('.wizard-btn.done'), 'last step shows a done button');
|
||||
assert.ok(exists('.wizard-btn.back'), 'shows the back button');
|
||||
});
|
||||
|
||||
|
|
|
@ -40,7 +40,10 @@ export default function() {
|
|||
title: 'hello there',
|
||||
index: 0,
|
||||
description: 'hello!',
|
||||
fields: [{ id: 'full_name', type: 'text', required: true }],
|
||||
fields: [{ id: 'full_name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
description: "Your name" }],
|
||||
next: 'second-step'
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
.select2-results .select2-highlighted {
|
||||
background: dark-light-diff($highlight, $secondary, 50%, -80%);
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.category-combobox, .select2-drop {
|
||||
|
||||
.badge-category {
|
||||
|
|
|
@ -332,11 +332,6 @@ Version: @@ver@@ Timestamp: @@timestamp@@
|
|||
.select2-results-dept-6 .select2-result-label { padding-left: 110px }
|
||||
.select2-results-dept-7 .select2-result-label { padding-left: 120px }
|
||||
|
||||
.select2-results .select2-highlighted {
|
||||
background: dark-light-diff($highlight, $secondary, 50%, -80%);
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.select2-results li em {
|
||||
background: #feffde;
|
||||
font-style: normal;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
@import "vendor/normalize";
|
||||
@import "vendor/font_awesome/font-awesome";
|
||||
@import "vendor/select2";
|
||||
|
||||
body {
|
||||
body.wizard {
|
||||
background-color: #fff;
|
||||
background-image: url('/images/wizard/bubbles.png');
|
||||
background-repeat: repeat;
|
||||
|
@ -12,6 +13,10 @@ body {
|
|||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.select {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.wizard-column {
|
||||
background-color: white;
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,0.2);
|
||||
|
@ -77,10 +82,10 @@ body {
|
|||
background-color: #6699ff;
|
||||
color: white;
|
||||
border: 0px;
|
||||
float: right;
|
||||
padding: 0.5em;
|
||||
outline: 0;
|
||||
transition: background-color .3s;
|
||||
margin-right: 0.5em;
|
||||
|
||||
&:hover {
|
||||
background-color: #80B3FF;
|
||||
|
@ -131,6 +136,25 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
button.wizard-btn:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
button.wizard-btn.done {
|
||||
background-color: #33B333;
|
||||
|
||||
&:hover {
|
||||
background-color: #4DCD4D;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #66E666;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #006700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wizard-field {
|
||||
|
@ -142,6 +166,16 @@ body {
|
|||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.field-error-description {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.field-description {
|
||||
color: #999;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
&.text-field {
|
||||
input {
|
||||
width: 100%;
|
||||
|
|
|
@ -9,7 +9,16 @@ class StepsController < ApplicationController
|
|||
def update
|
||||
updater = Wizard::StepUpdater.new(current_user, params[:id])
|
||||
updater.update(params[:fields])
|
||||
render nothing: true
|
||||
|
||||
if updater.success?
|
||||
render json: success_json
|
||||
else
|
||||
errors = []
|
||||
updater.errors.messages.each do |field, msg|
|
||||
errors << {field: field, description: msg.join }
|
||||
end
|
||||
render json: { errors: errors }, status: 422
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class WizardFieldSerializer < ApplicationSerializer
|
||||
|
||||
attributes :id, :type, :required, :value, :label, :placeholder
|
||||
attributes :id, :type, :required, :value, :label, :placeholder, :description, :options
|
||||
|
||||
def id
|
||||
object.id
|
||||
|
@ -41,4 +41,23 @@ class WizardFieldSerializer < ApplicationSerializer
|
|||
def include_placeholder?
|
||||
placeholder.present?
|
||||
end
|
||||
|
||||
def description
|
||||
I18n.t("#{i18n_key}.description", default: '')
|
||||
end
|
||||
|
||||
def include_description?
|
||||
description.present?
|
||||
end
|
||||
|
||||
def options
|
||||
object.options.map do |o|
|
||||
{id: o, label: I18n.t("#{i18n_key}.options.#{o}")}
|
||||
end
|
||||
end
|
||||
|
||||
def include_options?
|
||||
object.options.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<%= stylesheet_link_tag 'wizard' %>
|
||||
<%= script 'wizard-vendor' %>
|
||||
<%= script 'ember_jquery' %>
|
||||
<%= script 'wizard-vendor' %>
|
||||
<%= script 'wizard-application' %>
|
||||
<%= script "locales/#{I18n.locale}" %>
|
||||
<%= render partial: "common/special_font_face" %>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<title><%= t 'wizard.title' %></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class='wizard'>
|
||||
<div id='wizard-main'></div>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>QUnit Test Runner</title>
|
||||
<%= stylesheet_link_tag "qunit" %>
|
||||
<%= stylesheet_link_tag "test_helper" %>
|
||||
<%= stylesheet_link_tag "wizard" %>
|
||||
<%= javascript_include_tag "qunit" %>
|
||||
<%= javascript_include_tag "wizard/test/test_helper" %>
|
||||
<%= csrf_meta_tags %>
|
||||
|
|
|
@ -3227,6 +3227,7 @@ en:
|
|||
|
||||
wizard_js:
|
||||
wizard:
|
||||
done: "Done"
|
||||
back: "Back"
|
||||
next: "Next"
|
||||
step: "Step %{current} of %{total}"
|
||||
|
|
|
@ -3233,4 +3233,27 @@ en:
|
|||
contact_email:
|
||||
label: "Contact E-mail"
|
||||
placeholder: "name@example.com"
|
||||
description: "The key contact responsible for this site. This is used for critical notifications such as unhandled flags and on the \"About\" page for urgent matters."
|
||||
contact_url:
|
||||
label: "Contact URL"
|
||||
placeholder: "http://www.example.com/contact-us"
|
||||
description: "Will be displayed on your \"About\" page."
|
||||
site_contact_username:
|
||||
label: "Site Contact Username"
|
||||
description: "All automated messages will be sent from this user."
|
||||
colors:
|
||||
title: "Choose a Color Scheme"
|
||||
fields:
|
||||
color_scheme:
|
||||
label: "Color Scheme"
|
||||
options:
|
||||
default: "Default Scheme"
|
||||
dark: "Dark Scheme"
|
||||
|
||||
finished:
|
||||
title: "Your Discourse Forum is Ready!"
|
||||
description: |
|
||||
<p>If you ever feel like changing these settings, visit your admin section.</p>
|
||||
|
||||
<p>Have fun and enjoy your new community!</p>
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ class Wizard
|
|||
step.previous = last_step
|
||||
step.index = last_step.index + 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def self.build
|
||||
|
@ -38,9 +37,20 @@ class Wizard
|
|||
wizard.append_step(title)
|
||||
|
||||
contact = wizard.create_step('contact')
|
||||
contact.add_field(id: 'contact_email', type: 'text', required: true)
|
||||
contact.add_field(id: 'contact_email', type: 'text', required: true, value: SiteSetting.contact_email)
|
||||
contact.add_field(id: 'contact_url', type: 'text', value: SiteSetting.contact_url)
|
||||
contact.add_field(id: 'site_contact_username', type: 'text', value: SiteSetting.site_contact_username)
|
||||
wizard.append_step(contact)
|
||||
|
||||
theme = wizard.create_step('colors')
|
||||
scheme = theme.add_field(id: 'color_scheme', type: 'dropdown', required: true)
|
||||
scheme.add_option('default')
|
||||
scheme.add_option('dark')
|
||||
wizard.append_step(theme)
|
||||
|
||||
finished = wizard.create_step('finished')
|
||||
wizard.append_step(finished);
|
||||
|
||||
wizard
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class Wizard
|
||||
class Field
|
||||
attr_reader :id, :type, :required, :value
|
||||
|
||||
attr_reader :id, :type, :required, :value, :options
|
||||
attr_accessor :step
|
||||
|
||||
def initialize(attrs)
|
||||
|
@ -10,6 +11,12 @@ class Wizard
|
|||
@type = attrs[:type]
|
||||
@required = !!attrs[:required]
|
||||
@value = attrs[:value]
|
||||
@options = []
|
||||
end
|
||||
|
||||
def add_option(id)
|
||||
@options << id
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
class Wizard
|
||||
class StepUpdater
|
||||
|
||||
attr_accessor :errors
|
||||
include ActiveModel::Model
|
||||
|
||||
def initialize(current_user, id)
|
||||
@current_user = current_user
|
||||
@id = id
|
||||
@errors = []
|
||||
end
|
||||
|
||||
def update(fields)
|
||||
updater_method = "update_#{@id.underscore}".to_sym
|
||||
|
||||
if respond_to?(updater_method)
|
||||
send(updater_method, fields.symbolize_keys)
|
||||
else
|
||||
raise Discourse::InvalidAccess.new
|
||||
end
|
||||
send(updater_method, fields.symbolize_keys) if respond_to?(updater_method)
|
||||
end
|
||||
|
||||
def update_forum_title(fields)
|
||||
|
@ -24,6 +17,12 @@ class Wizard
|
|||
update_setting(:site_description, fields, :site_description)
|
||||
end
|
||||
|
||||
def update_contact(fields)
|
||||
update_setting(:contact_email, fields, :contact_email)
|
||||
update_setting(:contact_url, fields, :contact_url)
|
||||
update_setting(:site_contact_username, fields, :site_contact_username)
|
||||
end
|
||||
|
||||
def success?
|
||||
@errors.blank?
|
||||
end
|
||||
|
@ -33,9 +32,10 @@ class Wizard
|
|||
def update_setting(id, fields, field_id)
|
||||
value = fields[field_id]
|
||||
value.strip! if value.is_a?(String)
|
||||
SiteSetting.set_and_log(id, value, @current_user)
|
||||
|
||||
SiteSetting.set_and_log(id, value, @current_user) if SiteSetting.send(id) != value
|
||||
rescue Discourse::InvalidParameters => e
|
||||
@errors << {field: field_id, description: e.message }
|
||||
errors.add(field_id, e.message)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,11 +4,35 @@ require_dependency 'wizard/step_updater'
|
|||
describe Wizard::StepUpdater do
|
||||
let(:user) { Fabricate(:admin) }
|
||||
|
||||
it "can update the forum title" do
|
||||
it "updates the forum title step" do
|
||||
updater = Wizard::StepUpdater.new(user, 'forum_title')
|
||||
updater.update(title: 'new forum title')
|
||||
updater.update(title: 'new forum title', site_description: 'neat place')
|
||||
|
||||
expect(updater.success?).to eq(true)
|
||||
expect(SiteSetting.title).to eq("new forum title")
|
||||
expect(SiteSetting.site_description).to eq("neat place")
|
||||
end
|
||||
|
||||
context "contact step" do
|
||||
let(:updater) { Wizard::StepUpdater.new(user, 'contact') }
|
||||
|
||||
it "updates the fields correctly" do
|
||||
updater.update(contact_email: 'eviltrout@example.com',
|
||||
contact_url: 'http://example.com/custom-contact-url',
|
||||
site_contact_username: user.username)
|
||||
|
||||
expect(updater.success?).to eq(true)
|
||||
expect(SiteSetting.contact_email).to eq("eviltrout@example.com")
|
||||
expect(SiteSetting.contact_url).to eq("http://example.com/custom-contact-url")
|
||||
expect(SiteSetting.site_contact_username).to eq(user.username)
|
||||
end
|
||||
|
||||
it "doesn't update when there are errors" do
|
||||
updater.update(contact_email: 'not-an-email',
|
||||
site_contact_username: 'not-a-username')
|
||||
expect(updater.success?).to eq(false)
|
||||
expect(updater.errors).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -16,7 +16,6 @@ describe Wizard do
|
|||
let(:step2) { wizard.create_step('second-step') }
|
||||
|
||||
it "adds the step correctly" do
|
||||
|
||||
expect(step1.index).to be_blank
|
||||
|
||||
wizard.append_step(step1)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
require 'rails_helper'
|
||||
require 'wizard'
|
||||
|
||||
describe Wizard::Step do
|
||||
|
||||
let(:wizard) { Wizard.new }
|
||||
let(:step) { wizard.create_step('test-step') }
|
||||
|
||||
it "supports fields and options" do
|
||||
expect(step.fields).to be_empty
|
||||
text = step.add_field(id: 'test', type: 'text')
|
||||
expect(step.fields).to eq([text])
|
||||
|
||||
dropdown = step.add_field(id: 'snacks', type: 'dropdown')
|
||||
dropdown.add_option(id: 'candy')
|
||||
dropdown.add_option(id: 'nachos')
|
||||
dropdown.add_option(id: 'pizza')
|
||||
|
||||
expect(step.fields).to eq([text, dropdown])
|
||||
expect(dropdown.options.size).to eq(3)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,6 +3,10 @@ require 'rails_helper'
|
|||
describe ExtraLocalesController do
|
||||
|
||||
context 'show' do
|
||||
before do
|
||||
I18n.locale = :en
|
||||
I18n.reload!
|
||||
end
|
||||
|
||||
it "needs a valid bundle" do
|
||||
get :show, bundle: 'made-up-bundle'
|
||||
|
|
|
@ -19,15 +19,15 @@ describe StepsController do
|
|||
log_in(:admin)
|
||||
end
|
||||
|
||||
it "raises an error with an invalid id" do
|
||||
xhr :put, :update, id: 'made-up-id', fields: { forum_title: "updated title" }
|
||||
expect(response).to_not be_success
|
||||
it "updates properly if you are staff" do
|
||||
xhr :put, :update, id: 'contact', fields: { contact_email: "eviltrout@example.com" }
|
||||
expect(response).to be_success
|
||||
expect(SiteSetting.contact_email).to eq("eviltrout@example.com")
|
||||
end
|
||||
|
||||
it "updates properly if you are staff" do
|
||||
xhr :put, :update, id: 'forum-title', fields: { title: "updated title" }
|
||||
expect(response).to be_success
|
||||
expect(SiteSetting.title).to eq("updated title")
|
||||
it "returns errors if the field has them" do
|
||||
xhr :put, :update, id: 'contact', fields: { contact_email: "not-an-email" }
|
||||
expect(response).to_not be_success
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue