validate tag format; rearranged specs
This commit is contained in:
Родитель
ae019bde01
Коммит
e364618bc8
|
@ -35,7 +35,8 @@ class CommentThread < Content
|
|||
validates_presence_of :course_id # do we really need this?
|
||||
validates_presence_of :commentable_id
|
||||
|
||||
validate :valid_tag_names
|
||||
validate :tag_names_valid
|
||||
validate :tag_names_unique
|
||||
|
||||
after_create :generate_notifications
|
||||
|
||||
|
@ -77,6 +78,10 @@ class CommentThread < Content
|
|||
end
|
||||
end
|
||||
|
||||
def self.tag_name_valid?(tag)
|
||||
!!(tag =~ RE_TAG)
|
||||
end
|
||||
|
||||
private
|
||||
def generate_notifications
|
||||
if subscribers or (author.followers if author)
|
||||
|
@ -101,9 +106,24 @@ private
|
|||
end
|
||||
end
|
||||
|
||||
def valid_tag_names
|
||||
unless tags_array.all? {|tag| tag =~ /^\w+(\s*\w+)*$/}
|
||||
errors.add :tag, "must consist of words, numbers, underscores and spaces only"
|
||||
RE_HEADCHAR = /[a-z0-9]/
|
||||
RE_ENDONLYCHAR = /\+/
|
||||
RE_ENDCHAR = /[a-z0-9\#]/
|
||||
RE_CHAR = /[a-z0-9\-\#\.]/
|
||||
RE_WORD = /#{RE_HEADCHAR}(((#{RE_CHAR})*(#{RE_ENDCHAR})+)?(#{RE_ENDONLYCHAR})*)?/
|
||||
RE_TAG = /^#{RE_WORD}( #{RE_WORD})*$/
|
||||
|
||||
|
||||
|
||||
def tag_names_valid
|
||||
unless tags_array.all? {|tag| self.class.tag_name_valid? tag}
|
||||
errors.add :tag, "can consist of words, numbers, dashes and spaces only and cannot start with dash"
|
||||
end
|
||||
end
|
||||
|
||||
def tag_names_unique
|
||||
unless tags_array.uniq.size == tags_array.size
|
||||
errors.add :tags, "must be unique"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -50,26 +50,49 @@ describe "app" do
|
|||
end
|
||||
end
|
||||
describe "POST /api/v1/:commentable_id/threads" do
|
||||
default_params = {title: "Interesting question", body: "cool", course_id: "1", user_id: "1"}
|
||||
it "create a new comment thread for the commentable object" do
|
||||
post '/api/v1/question_1/threads', title: "Interesting question", body: "cool", course_id: "1", user_id: "1"
|
||||
post '/api/v1/question_1/threads', default_params
|
||||
last_response.should be_ok
|
||||
CommentThread.count.should == 3
|
||||
CommentThread.where(title: "Interesting question").first.should_not be_nil
|
||||
end
|
||||
it "allows anonymous thread" do
|
||||
post '/api/v1/question_1/threads', title: "Interesting question", body: "cool", course_id: "1"
|
||||
params = default_params.dup
|
||||
params.delete(:user_id)
|
||||
post '/api/v1/question_1/threads', params
|
||||
last_response.should be_ok
|
||||
CommentThread.count.should == 3
|
||||
CommentThread.where(title: "Interesting question").first.should_not be_nil
|
||||
end
|
||||
it "create a new comment thread for a new commentable object" do
|
||||
post '/api/v1/does_not_exist/threads', title: "Interesting question", body: "cool", course_id: "1", user_id: "1"
|
||||
post '/api/v1/does_not_exist/threads', default_params
|
||||
last_response.should be_ok
|
||||
Commentable.find("does_not_exist").comment_threads.length.should == 1
|
||||
Commentable.find("does_not_exist").comment_threads.first.body.should == "cool"
|
||||
end
|
||||
it "create a new comment thread with tag" do
|
||||
post '/api/v1/question_1/threads', title: "Interesting question", body: "cool", course_id: "1", user_id: "1", tags: "a, b, c"
|
||||
post '/api/v1/question_1/threads', default_params.merge(tags: "a, b, c")
|
||||
last_response.should be_ok
|
||||
CommentThread.count.should == 3
|
||||
thread = CommentThread.where(title: "Interesting question").first
|
||||
thread.tags_array.length.should == 3
|
||||
thread.tags_array.should include "a"
|
||||
thread.tags_array.should include "b"
|
||||
thread.tags_array.should include "c"
|
||||
end
|
||||
it "strip spaces in tags" do
|
||||
post '/api/v1/question_1/threads', default_params.merge(tags: " a, b ,c ")
|
||||
last_response.should be_ok
|
||||
CommentThread.count.should == 3
|
||||
thread = CommentThread.where(title: "Interesting question").first
|
||||
thread.tags_array.length.should == 3
|
||||
thread.tags_array.should include "a"
|
||||
thread.tags_array.should include "b"
|
||||
thread.tags_array.should include "c"
|
||||
end
|
||||
it "accepts [a-z 0-9 + # - .]words, numbers, dashes, spaces but no underscores in tags" do
|
||||
post '/api/v1/question_1/threads', default_params.merge(tags: "artificial-intelligence, machine-learning, 7-is-a-lucky-number, interesting problem")
|
||||
last_response.should be_ok
|
||||
CommentThread.count.should == 3
|
||||
thread = CommentThread.where(title: "Interesting question").first
|
|
@ -0,0 +1,54 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "app" do
|
||||
describe "search" do
|
||||
before(:each) { init_without_subscriptions }
|
||||
describe "GET /api/v1/search/tags" do
|
||||
it "returns all threads tagged with all tags" do
|
||||
require 'uri'
|
||||
thread1 = CommentThread.all.to_a.first
|
||||
thread2 = CommentThread.all.to_a.last
|
||||
ai = "artificial intelligence"
|
||||
ml = "marchine learning"
|
||||
random1 = "random1"
|
||||
random2 = "random2"
|
||||
random3 = "random3"
|
||||
thread1.tags = [ai, ml, random1].join ","
|
||||
thread1.save
|
||||
thread2.tags = [ai, ml, random2].join ","
|
||||
thread2.save
|
||||
|
||||
post "/api/v1/search/tags", tags: [ai, ml]
|
||||
last_response.should be_ok
|
||||
threads = parse last_response.body
|
||||
threads.length.should == 2
|
||||
threads.select{|t| t["id"] == thread1.id.to_s}.first.should_not be_nil
|
||||
threads.select{|t| t["id"] == thread2.id.to_s}.first.should_not be_nil
|
||||
|
||||
post "/api/v1/search/tags", tags: [ai]
|
||||
last_response.should be_ok
|
||||
threads = parse last_response.body
|
||||
threads.length.should == 2
|
||||
threads.select{|t| t["id"] == thread1.id.to_s}.first.should_not be_nil
|
||||
threads.select{|t| t["id"] == thread2.id.to_s}.first.should_not be_nil
|
||||
|
||||
post "/api/v1/search/tags", tags: [ai, random1]
|
||||
last_response.should be_ok
|
||||
threads = parse last_response.body
|
||||
threads.length.should == 1
|
||||
threads.select{|t| t["id"] == thread1.id.to_s}.first.should_not be_nil
|
||||
|
||||
post "/api/v1/search/tags", tags: [random1]
|
||||
last_response.should be_ok
|
||||
threads = parse last_response.body
|
||||
threads.length.should == 1
|
||||
threads.select{|t| t["id"] == thread1.id.to_s}.first.should_not be_nil
|
||||
|
||||
post "/api/v1/search/tags", tags: [random1, random2]
|
||||
last_response.should be_ok
|
||||
threads = parse last_response.body
|
||||
threads.length.should == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe CommentThread do
|
||||
it "validates tag name" do
|
||||
CommentThread.tag_name_valid?("a++").should be_true
|
||||
CommentThread.tag_name_valid?("a++ b++ c++").should be_true
|
||||
CommentThread.tag_name_valid?("a#b+").should be_true
|
||||
CommentThread.tag_name_valid?("a##").should be_true
|
||||
CommentThread.tag_name_valid?("a#-b#").should be_true
|
||||
CommentThread.tag_name_valid?("000a123").should be_true
|
||||
CommentThread.tag_name_valid?("artificial-intelligence").should be_true
|
||||
CommentThread.tag_name_valid?("artificial intelligence").should be_true
|
||||
CommentThread.tag_name_valid?("well-known formulas").should be_true
|
||||
|
||||
CommentThread.tag_name_valid?("a#+b#").should be_false
|
||||
CommentThread.tag_name_valid?("a# +b#").should be_false
|
||||
CommentThread.tag_name_valid?("--a").should be_false
|
||||
CommentThread.tag_name_valid?("artificial_intelligence").should be_false
|
||||
CommentThread.tag_name_valid?("#this-is-a-tag").should be_false
|
||||
CommentThread.tag_name_valid?("_this-is-a-tag").should be_false
|
||||
CommentThread.tag_name_valid?("this-is+a-tag").should be_false
|
||||
end
|
||||
end
|
Загрузка…
Ссылка в новой задаче