mirror of
https://github.com/ENSL/ensl.org.git
synced 2025-01-15 22:30:53 +00:00
Merge pull request #15 from cblanc/shoutbox_tweaks
Shoutbox Client-side validation
This commit is contained in:
commit
bc3723191b
11 changed files with 255 additions and 68 deletions
|
@ -193,7 +193,7 @@ GEM
|
||||||
rake (10.3.2)
|
rake (10.3.2)
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
rmagick (2.13.2)
|
rmagick (2.13.4)
|
||||||
rspec-core (2.14.8)
|
rspec-core (2.14.8)
|
||||||
rspec-expectations (2.14.5)
|
rspec-expectations (2.14.5)
|
||||||
diff-lcs (>= 1.1.3, < 2.0)
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
|
@ -298,7 +298,7 @@ DEPENDENCIES
|
||||||
quiet_assets (~> 1.0.2)
|
quiet_assets (~> 1.0.2)
|
||||||
rails (~> 3.2.19)
|
rails (~> 3.2.19)
|
||||||
rails_autolink (~> 1.1.5)
|
rails_autolink (~> 1.1.5)
|
||||||
rmagick (~> 2.13.2)
|
rmagick (~> 2.13.4)
|
||||||
rspec-rails (~> 2.14.1)
|
rspec-rails (~> 2.14.1)
|
||||||
sanitize (~> 2.1.0)
|
sanitize (~> 2.1.0)
|
||||||
sass (~> 3.3.4)
|
sass (~> 3.3.4)
|
||||||
|
|
|
@ -6,43 +6,5 @@
|
||||||
//= require tinymce-jquery
|
//= require tinymce-jquery
|
||||||
//= require yetii
|
//= require yetii
|
||||||
//= require local
|
//= require local
|
||||||
//= require_self
|
//= require shoutbox
|
||||||
|
//= require misc
|
||||||
$ ->
|
|
||||||
$('#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>"
|
|
38
app/assets/javascripts/misc.js.coffee
Normal file
38
app/assets/javascripts/misc.js.coffee
Normal 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>"
|
76
app/assets/javascripts/shoutbox.js
Normal file
76
app/assets/javascripts/shoutbox.js
Normal 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);
|
||||||
|
};
|
|
@ -29,11 +29,4 @@ class ShoutmsgsController < ApplicationController
|
||||||
@shoutmsg.destroy
|
@shoutmsg.destroy
|
||||||
redirect_to_back
|
redirect_to_back
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def render_shoutmsgs shoutable_type = nil, shoutable_id = nil
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,3 +17,11 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
ShoutboxController({
|
||||||
|
context: $('<%= "#new_#{shoutmsg.domain}" %>')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -3,4 +3,12 @@ FactoryGirl.define do
|
||||||
sequence(:name) { |n| "Category #{n}" }
|
sequence(:name) { |n| "Category #{n}" }
|
||||||
sequence(:sort) { |n| n }
|
sequence(:sort) { |n| n }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :news do
|
||||||
|
domain Category::DOMAIN_NEWS
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :game do
|
||||||
|
domain Category::DOMAIN_GAMES
|
||||||
|
end
|
||||||
end
|
end
|
13
spec/factories/gather.rb
Normal file
13
spec/factories/gather.rb
Normal 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
|
37
spec/features/gathers/gathers_spec.rb
Normal file
37
spec/features/gathers/gathers_spec.rb
Normal 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
|
|
@ -1,26 +1,34 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
feature 'Shoutbox' do
|
feature 'Shoutbox', js: true do
|
||||||
|
let!(:user) { create :user }
|
||||||
|
|
||||||
background do
|
background do
|
||||||
@user = create :user
|
sign_in_as user
|
||||||
sign_in_as @user
|
|
||||||
visit root_path
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature 'user creates a shout', js: true do
|
scenario 'creating a valid shout' do
|
||||||
scenario 'shouting with valid content' do
|
visit root_path
|
||||||
shout = rand(100000).to_s
|
shout = rand(100000).to_s
|
||||||
fill_in 'shoutbox_text', with: shout
|
fill_in 'shoutbox_text', with: shout
|
||||||
click_button 'Shout!'
|
click_button 'Shout!'
|
||||||
expect(page).to have_content(shout)
|
expect(page).to have_content(shout)
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'unable to while banned' do
|
scenario 'enter more than 100 characters' do
|
||||||
@user.bans.create! ban_type: Ban::TYPE_MUTE, expiry: Time.now + 10.days
|
valid_shout = 100.times.map { "a" }.join
|
||||||
shout = rand(100000).to_s
|
invalid_shout = 101.times.map { "a" }.join
|
||||||
fill_in 'shoutbox_text', with: shout
|
visit root_path
|
||||||
click_button 'Shout!'
|
expect(page).to_not have_content("Maximum shout length exceeded")
|
||||||
expect(page).to_not have_content(shout)
|
fill_in 'shoutbox_text', with: invalid_shout
|
||||||
end
|
expect(page).to have_content("Maximum shout length exceeded")
|
||||||
end
|
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
|
end
|
44
spec/models/user_spec.rb
Normal file
44
spec/models/user_spec.rb
Normal 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
|
Loading…
Reference in a new issue