Merge pull request #15 from cblanc/shoutbox_tweaks

Shoutbox Client-side validation
This commit is contained in:
simplefl 2015-05-09 17:59:55 +02:00
commit bc3723191b
11 changed files with 255 additions and 68 deletions

View file

@ -193,7 +193,7 @@ GEM
rake (10.3.2)
rdoc (3.12.2)
json (~> 1.4)
rmagick (2.13.2)
rmagick (2.13.4)
rspec-core (2.14.8)
rspec-expectations (2.14.5)
diff-lcs (>= 1.1.3, < 2.0)
@ -298,7 +298,7 @@ DEPENDENCIES
quiet_assets (~> 1.0.2)
rails (~> 3.2.19)
rails_autolink (~> 1.1.5)
rmagick (~> 2.13.2)
rmagick (~> 2.13.4)
rspec-rails (~> 2.14.1)
sanitize (~> 2.1.0)
sass (~> 3.3.4)

View file

@ -6,43 +6,5 @@
//= require tinymce-jquery
//= require yetii
//= require local
//= require_self
$ ->
$('#logout').click ->
$(this).closest('form').submit()
$('select').each (i, el) ->
$select = $(el)
$select.wrap '<div class="select-wrapper" />'
$select.on 'DOMSubtreeModified', (event) ->
$el = $(this)
$wrapper = $el.parent()
if $el.is("[disabled]")
$wrapper.addClass 'disabled'
else
$wrapper.removeClass 'disabled'
$select.trigger 'DOMSubtreeModified'
$('a[href=#form_submit]').click ->
$(this).closest('form').submit()
return false
$('select.autosubmit').change ->
$(this).closest('form').submit()
$('#notification').delay(3000).fadeOut()
$('#steam-search a').click (event) ->
event.preventDefault()
$search = $('#steam-search')
id = $search.data 'user-id'
$search.html "<p>Searching...</p>"
$.get "/api/v1/users/#{id}", (data) ->
$search.html "<a href='#{data.steam.url}'>Steam Profile: #{data.steam.nickname}</a>"
//= require shoutbox
//= require misc

View file

@ -0,0 +1,38 @@
$ ->
$('#logout').click ->
$(this).closest('form').submit()
$('select').each (i, el) ->
$select = $(el)
$select.wrap '<div class="select-wrapper" />'
$select.on 'DOMSubtreeModified', (event) ->
$el = $(this)
$wrapper = $el.parent()
if $el.is("[disabled]")
$wrapper.addClass 'disabled'
else
$wrapper.removeClass 'disabled'
$select.trigger 'DOMSubtreeModified'
$('a[href=#form_submit]').click ->
$(this).closest('form').submit()
return false
$('select.autosubmit').change ->
$(this).closest('form').submit()
$('#notification').delay(3000).fadeOut()
$('#steam-search a').click (event) ->
event.preventDefault()
$search = $('#steam-search')
id = $search.data 'user-id'
$search.html "<p>Searching...</p>"
$.get "/api/v1/users/#{id}", (data) ->
$search.html "<a href='#{data.steam.url}'>Steam Profile: #{data.steam.nickname}</a>"

View file

@ -0,0 +1,76 @@
// Shoutbox Controller manages input validation on shoutmsg form
function ShoutboxController (options) {
if (!(this instanceof ShoutboxController)) {
return new ShoutboxController(options);
}
this.options = options;
this.$context = options.context;
if (this.$context.length) {
this.init(options);
} else {
console.log("Unable to initialize shoutbox controller. No context provided");
}
return this;
}
// Initialise shoutbox state
ShoutboxController.prototype.init = function (options) {
var self = this;
self.$input = self.$context.find(".shout_input");
self.$button = self.$context.find('input[type="submit"]');
self.$messageBox = null;
self.$input.bind("keyup change", function () {
if (self.$input.val().length > 100) {
self.disableShoutbox();
} else {
self.enableShoutbox();
}
});
return self;
};
// Displays a message if `message` present, otherwise removes message elemt
ShoutboxController.prototype.writeMessage = function (message) {
if (message === undefined) return this.removeMessageBox();
this.createMessageBox().html(message);
return this;
};
// Adds message box to DOM and cache
ShoutboxController.prototype.createMessageBox = function () {
if (this.$messageBox) return this.$messageBox;
this.$messageBox = $("<p/>", {class: "shout-warning"}).appendTo(this.$context.find(".fields"));
return this.$messageBox;
};
// Removes message box from DOM and cache
ShoutboxController.prototype.removeMessageBox = function () {
if (this.$messageBox) {
this.$messageBox.remove();
this.$messageBox = null;
}
return this;
};
// Returns true if button is disabled
ShoutboxController.prototype.isDisabled = function () {
return this.$button.prop("disabled") === true;
};
// Disables Input Button
ShoutboxController.prototype.disableShoutbox = function () {
var chars = this.$input.val().length;
this.writeMessage(["Maximum shout length exceeded (",chars,"/100)"].join(""));
this.$button.prop("disabled", true);
};
// Removes any warnings and enableds shoutbox submit
ShoutboxController.prototype.enableShoutbox = function () {
if (!this.$button.prop("disabled")) {
return this;
}
// Remove any warnings
this.writeMessage();
this.$button.prop("disabled", false);
};

View file

@ -29,11 +29,4 @@ class ShoutmsgsController < ApplicationController
@shoutmsg.destroy
redirect_to_back
end
private
def render_shoutmsgs shoutable_type = nil, shoutable_id = nil
end
end

View file

@ -17,3 +17,11 @@
<% end %>
<% end %>
<% end %>
<script type="text/javascript">
$(function () {
ShoutboxController({
context: $('<%= "#new_#{shoutmsg.domain}" %>')
});
});
</script>

View file

@ -3,4 +3,12 @@ FactoryGirl.define do
sequence(:name) { |n| "Category #{n}" }
sequence(:sort) { |n| n }
end
trait :news do
domain Category::DOMAIN_NEWS
end
trait :game do
domain Category::DOMAIN_GAMES
end
end

13
spec/factories/gather.rb Normal file
View file

@ -0,0 +1,13 @@
FactoryGirl.define do
factory :gather do
association :category, factory: [:category, :game]
end
trait :running do
status Gather::STATE_RUNNING
end
trait :picking do
status Gather::STATE_PICKING
end
end

View file

@ -0,0 +1,37 @@
require 'spec_helper'
feature 'Gathers', js: true do
let!(:user) { create :user }
let!(:gather) { create :gather, :running }
feature 'Shoutbox' do
background do
sign_in_as user
end
scenario 'create shout' do
visit gather_path(gather)
shout = rand(100000).to_s
fill_in "shout_Gather_#{gather.id}_text", with: shout
click_button 'Shout!'
expect(page).to have_content(shout)
end
scenario 'enter more than 100 characters' do
valid_shout = 100.times.map { "a" }.join
invalid_shout = 101.times.map { "a" }.join
visit gather_path(gather)
expect(page).to_not have_content("Maximum shout length exceeded")
fill_in "shout_Gather_#{gather.id}_text", with: invalid_shout
expect(page).to have_content("Maximum shout length exceeded")
fill_in "shout_Gather_#{gather.id}_text", with: valid_shout
expect(page).to_not have_content("Maximum shout length exceeded")
end
scenario 'creating shout while banned' do
Ban.create! ban_type: Ban::TYPE_MUTE, expiry: Time.now + 10.days, user_name: user.username
visit root_path
expect(find("#sidebar")).to have_content "You have been muted."
end
end
end

View file

@ -1,26 +1,34 @@
require 'spec_helper'
feature 'Shoutbox' do
feature 'Shoutbox', js: true do
let!(:user) { create :user }
background do
@user = create :user
sign_in_as @user
visit root_path
sign_in_as user
end
feature 'user creates a shout', js: true do
scenario 'shouting with valid content' do
shout = rand(100000).to_s
fill_in 'shoutbox_text', with: shout
click_button 'Shout!'
expect(page).to have_content(shout)
end
scenario 'creating a valid shout' do
visit root_path
shout = rand(100000).to_s
fill_in 'shoutbox_text', with: shout
click_button 'Shout!'
expect(page).to have_content(shout)
end
scenario 'unable to while banned' do
@user.bans.create! ban_type: Ban::TYPE_MUTE, expiry: Time.now + 10.days
shout = rand(100000).to_s
fill_in 'shoutbox_text', with: shout
click_button 'Shout!'
expect(page).to_not have_content(shout)
end
end
scenario 'enter more than 100 characters' do
valid_shout = 100.times.map { "a" }.join
invalid_shout = 101.times.map { "a" }.join
visit root_path
expect(page).to_not have_content("Maximum shout length exceeded")
fill_in 'shoutbox_text', with: invalid_shout
expect(page).to have_content("Maximum shout length exceeded")
fill_in 'shoutbox_text', with: valid_shout
expect(page).to_not have_content("Maximum shout length exceeded")
end
scenario 'creating shout while banned' do
Ban.create! ban_type: Ban::TYPE_MUTE, expiry: Time.now + 10.days, user_name: user.username
visit root_path
expect(find("#sidebar")).to have_content "You have been muted."
end
end

44
spec/models/user_spec.rb Normal file
View file

@ -0,0 +1,44 @@
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# username :string(255)
# password :string(255)
# firstname :string(255)
# lastname :string(255)
# email :string(255)
# steamid :string(255)
# team_id :integer
# lastvisit :datetime
# created_at :datetime
# updated_at :datetime
# lastip :string(255)
# country :string(255)
# birthdate :date
# time_zone :string(255)
# version :integer
# public_email :boolean default(FALSE), not null
#
require 'spec_helper'
describe User do
let!(:user) { create :user }
describe "#banned?" do
it "returns false if user is not banned" do
expect(user.banned?).to be_false
end
it "returns true if user is banned" do
ban = Ban.create! ban_type: Ban::TYPE_SITE, expiry: Time.now + 10.days, user_name: user.username
expect(user.banned?).to be_true
end
it "returns true for specific bans" do
ban = Ban.create! ban_type: Ban::TYPE_MUTE, expiry: Time.now + 10.days, user_name: user.username
expect(user.banned? Ban::TYPE_MUTE).to be_true
end
end
end