parent
7a8497420e
commit
6799938325
2
Gemfile
2
Gemfile
|
@ -43,7 +43,7 @@ group :test, :development do
|
|||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem "rspec-rails"
|
||||
gem "machinist"
|
||||
gem "factory_bot_rails"
|
||||
gem "rubocop", require: false
|
||||
gem "sqlite3"
|
||||
gem "faker"
|
||||
|
|
|
@ -71,6 +71,11 @@ GEM
|
|||
actionmailer (>= 4.0, < 6)
|
||||
activesupport (>= 4.0, < 6)
|
||||
execjs (2.7.0)
|
||||
factory_bot (4.10.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.10.0)
|
||||
factory_bot (~> 4.10.0)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.8.7)
|
||||
i18n (>= 0.7)
|
||||
globalid (0.4.1)
|
||||
|
@ -87,7 +92,6 @@ GEM
|
|||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
machinist (2.0)
|
||||
mail (2.7.0)
|
||||
mini_mime (>= 0.1.1)
|
||||
method_source (0.9.0)
|
||||
|
@ -207,11 +211,11 @@ DEPENDENCIES
|
|||
commonmarker (~> 0.14)
|
||||
dynamic_form
|
||||
exception_notification
|
||||
factory_bot_rails
|
||||
faker
|
||||
htmlentities
|
||||
jquery-rails (~> 4.3)
|
||||
json
|
||||
machinist
|
||||
mail
|
||||
mysql2 (~> 0.3.20)
|
||||
nokogiri (>= 1.7.2)
|
||||
|
|
|
@ -40,6 +40,10 @@ module Lobsters
|
|||
config.after_initialize do
|
||||
require "#{Rails.root}/lib/monkey.rb"
|
||||
end
|
||||
|
||||
config.generators do |g|
|
||||
g.factory_bot false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
describe TagsController do
|
||||
let(:user_id) { 5 }
|
||||
let(:user) { create(:user) }
|
||||
before do
|
||||
stub_login_as User.make!(id: user_id)
|
||||
stub_login_as user
|
||||
allow(controller).to receive(:require_logged_in_admin)
|
||||
end
|
||||
|
||||
|
@ -41,7 +41,7 @@ describe TagsController do
|
|||
post :create, params: { tag: { tag: 'mytag' } }
|
||||
mod = Moderation.order(id: :desc).first
|
||||
expect(mod.tag_id).to eq Tag.order(id: :desc).first.id
|
||||
expect(mod.moderator_user_id).to eq user_id
|
||||
expect(mod.moderator_user_id).to eq user.id
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -83,7 +83,7 @@ describe TagsController do
|
|||
|
||||
it 'creates a moderation with the expected user_id' do
|
||||
post :update, params: { id: tag.id, tag: { tag: 'modified_tag' } }
|
||||
expect(Moderation.order(id: :desc).first.moderator_user_id).to eq user_id
|
||||
expect(Moderation.order(id: :desc).first.moderator_user_id).to eq user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
FactoryBot.define do
|
||||
factory :comment do
|
||||
association(:user)
|
||||
association(:story)
|
||||
sequence(:comment) {|n| "comment text #{n}" }
|
||||
created_at { Time.current }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
FactoryBot.define do
|
||||
factory :hat do
|
||||
association(:user)
|
||||
sequence(:hat) {|n| "hat #{n}" }
|
||||
association(:granted_by_user, factory: :user)
|
||||
link 'http://example.com'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
FactoryBot.define do
|
||||
factory :message do
|
||||
association(:recipient, factory: :user)
|
||||
association(:author, factory: :user)
|
||||
sequence(:subject) {|n| "message subject #{n}" }
|
||||
sequence(:body) {|n| "message body #{n}" }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
FactoryBot.define do
|
||||
factory :story do
|
||||
association(:user)
|
||||
sequence(:title) {|n| "story title #{n}" }
|
||||
sequence(:url) {|n| "http://example.com/#{n}" }
|
||||
tags_a ["tag1", "tag2"]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
FactoryBot.define do
|
||||
factory :tag do
|
||||
sequence(:tag) {|n| "tag-#{n}" }
|
||||
sequence(:description) {|n| "tag #{n}" }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
FactoryBot.define do
|
||||
factory :user do
|
||||
sequence(:email) {|n| "user-#{n}@example.com" }
|
||||
sequence(:username) {|n| "username#{n}" }
|
||||
password { "blah blah" }
|
||||
password_confirmation(&:password)
|
||||
trait(:banned) do
|
||||
transient do
|
||||
banner nil
|
||||
end
|
||||
banned_at { Time.current }
|
||||
banned_reason "some reason"
|
||||
banned_by_user_id { banner && banner.id }
|
||||
end
|
||||
trait(:noinvite) do
|
||||
transient do
|
||||
disabler nil
|
||||
end
|
||||
disabled_invite_at { Time.current }
|
||||
disabled_invite_reason "some reason"
|
||||
disabled_invite_by_user_id { disabler && disabler.id }
|
||||
end
|
||||
trait(:inactive) do
|
||||
username { 'inactive-user' }
|
||||
to_create {|user| user.save(validate: false) }
|
||||
end
|
||||
trait(:admin) do
|
||||
is_admin true
|
||||
is_moderator true
|
||||
end
|
||||
trait(:moderator) do
|
||||
is_moderator true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
FactoryBot.define do
|
||||
factory :vote do
|
||||
vote 1
|
||||
end
|
||||
end
|
|
@ -4,8 +4,8 @@ require 'rails_helper'
|
|||
# so the call can't just be click_on('delete'), etc.
|
||||
|
||||
RSpec.feature "Commenting" do
|
||||
let(:story) { Story.make! title: "Example Story" }
|
||||
let(:user) { User.make! username: 'user' }
|
||||
let(:story) { create(:story) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before(:each) { stub_login_as user }
|
||||
|
||||
|
@ -20,12 +20,11 @@ RSpec.feature "Commenting" do
|
|||
|
||||
feature "deleting comments" do
|
||||
scenario 'deleting a comment' do
|
||||
comment = Comment.make!(
|
||||
comment: 'An example comment',
|
||||
user_id: user.id,
|
||||
story_id: story.id,
|
||||
created_at: 1.day.ago,
|
||||
)
|
||||
comment = create(:comment,
|
||||
user_id: user.id,
|
||||
story_id: story.id,
|
||||
created_at: 1.day.ago,
|
||||
)
|
||||
visit "/s/#{story.short_id}"
|
||||
expect(page).to have_link('delete')
|
||||
|
||||
|
@ -37,12 +36,7 @@ RSpec.feature "Commenting" do
|
|||
end
|
||||
|
||||
scenario 'trying to delete old comments' do
|
||||
comment = Comment.make!(
|
||||
comment: 'An example comment',
|
||||
user_id: user.id,
|
||||
story_id: story.id,
|
||||
created_at: 90.days.ago,
|
||||
)
|
||||
comment = create(:comment, user: user, story: story, created_at: 90.days.ago)
|
||||
visit "/s/#{story.short_id}"
|
||||
expect(page).not_to have_link('delete')
|
||||
|
||||
|
@ -55,9 +49,9 @@ RSpec.feature "Commenting" do
|
|||
feature "disowning comments" do
|
||||
scenario 'disowning a comment' do
|
||||
# bypass validations to create inactive-user:
|
||||
User.make!.tap {|u| u.update_column :username, 'inactive-user' }
|
||||
create(:user, :inactive)
|
||||
|
||||
comment = Comment.make! user_id: user.id, story_id: story.id, created_at: 90.days.ago
|
||||
comment = create(:comment, user_id: user.id, story_id: story.id, created_at: 90.days.ago)
|
||||
visit "/s/#{story.short_id}"
|
||||
expect(page).to have_link('disown')
|
||||
|
||||
|
@ -69,12 +63,11 @@ RSpec.feature "Commenting" do
|
|||
end
|
||||
|
||||
scenario 'trying to disown recent comments' do
|
||||
comment = Comment.make! user_id: user.id, story_id: story.id, created_at: 1.day.ago
|
||||
comment = create(:comment, user_id: user.id, story_id: story.id, created_at: 1.day.ago)
|
||||
visit "/s/#{story.short_id}"
|
||||
expect(page).not_to have_link('disown')
|
||||
|
||||
page.driver.post "/comments/#{comment.short_id}/disown"
|
||||
puts page.body
|
||||
comment.reload
|
||||
expect(comment.user).to eq(user)
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.feature "Reading Homepage", type: feature do
|
||||
let!(:story) { Story.make! title: "Example Story" }
|
||||
let!(:story) { create(:story) }
|
||||
|
||||
feature "when logged out" do
|
||||
scenario "reading a story" do
|
||||
|
@ -11,7 +11,7 @@ RSpec.feature "Reading Homepage", type: feature do
|
|||
end
|
||||
|
||||
feature "when logged in" do
|
||||
let(:user) { User.make! }
|
||||
let(:user) { create(:user) }
|
||||
before(:each) { stub_login_as user }
|
||||
|
||||
scenario "reading a story" do
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.feature "Reading Stories", type: :feature do
|
||||
let!(:story) { Story.make! title: "Example Story" }
|
||||
let!(:comment) { Comment.make! story_id: story.id, comment: "Example comment" }
|
||||
let!(:story) { create(:story) }
|
||||
let!(:comment) { create(:comment, story: story) }
|
||||
|
||||
feature "when logged out" do
|
||||
scenario "reading a story" do
|
||||
|
@ -13,7 +13,7 @@ RSpec.feature "Reading Stories", type: :feature do
|
|||
end
|
||||
|
||||
feature "when logged in" do
|
||||
let(:user) { User.make! }
|
||||
let(:user) { create(:user) }
|
||||
before(:each) { stub_login_as user }
|
||||
|
||||
scenario "reading a story" do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.feature "Submitting Stories", type: :feature do
|
||||
let(:user) { User.make! }
|
||||
let(:user) { create(:user) }
|
||||
before(:each) { stub_login_as user }
|
||||
|
||||
scenario "submitting a link" do
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.feature "User Administration" do
|
||||
let(:admin) { User.make! is_moderator: true, is_admin: true }
|
||||
let(:user) { User.make! username: 'user' }
|
||||
let(:banned) {
|
||||
User.make!(username: 'banned').tap {|u| u.ban_by_user_for_reason!(admin, 'why') }
|
||||
}
|
||||
let(:noinvite) {
|
||||
User.make!(username: 'noinvite').tap {|u| u.disable_invite_by_user_for_reason!(admin, 'why') }
|
||||
}
|
||||
let(:admin) { create(:user, :admin) }
|
||||
let(:user) { create(:user) }
|
||||
let(:banned) { create(:user, :banned, banner: admin) }
|
||||
let(:noinvite) { create(:user, :noinvite, disabler: admin) }
|
||||
|
||||
before(:each) { stub_login_as admin }
|
||||
|
||||
scenario 'diabling invites' do
|
||||
expect(user.can_invite?).to be(true)
|
||||
visit '/u/user'
|
||||
visit user_path(user)
|
||||
expect(page).to have_button('Disable Invites')
|
||||
fill_in 'Reason', with: 'Invited spammers'
|
||||
click_on 'Disable Invites'
|
||||
|
@ -27,7 +24,7 @@ RSpec.feature "User Administration" do
|
|||
|
||||
scenario 'enabling invites' do
|
||||
expect(noinvite.can_invite?).to be(false)
|
||||
visit '/u/noinvite'
|
||||
visit user_path(noinvite)
|
||||
click_on 'Enable Invites'
|
||||
expect(page).to have_content('invite capability enabled')
|
||||
noinvite.reload
|
||||
|
@ -39,7 +36,7 @@ RSpec.feature "User Administration" do
|
|||
|
||||
scenario 'banning' do
|
||||
expect(user.is_banned?).to be(false)
|
||||
visit '/u/user'
|
||||
visit user_path(user)
|
||||
expect(page).to have_button('Ban')
|
||||
fill_in 'Reason', with: 'Spammer'
|
||||
click_on 'Ban'
|
||||
|
@ -52,7 +49,7 @@ RSpec.feature "User Administration" do
|
|||
|
||||
scenario "unbanning" do
|
||||
expect(banned.is_banned?).to be(true)
|
||||
visit '/u/banned'
|
||||
visit user_path(banned)
|
||||
click_on 'Unban'
|
||||
expect(page).to have_content('unbanned')
|
||||
banned.reload
|
||||
|
|
|
@ -2,22 +2,22 @@ require "rails_helper"
|
|||
|
||||
describe Comment do
|
||||
it "should get a short id" do
|
||||
c = Comment.make!(:comment => "hello")
|
||||
c = create(:comment)
|
||||
|
||||
expect(c.short_id).to match(/^\A[a-zA-Z0-9]{1,10}\z/)
|
||||
end
|
||||
|
||||
describe "hat" do
|
||||
it "can't be worn if user doesn't have that hat" do
|
||||
comment = Comment.make(hat: Hat.make!)
|
||||
comment = build(:comment, hat: build(:hat))
|
||||
comment.valid?
|
||||
expect(comment.errors[:hat]).to eq(['not wearable by user'])
|
||||
end
|
||||
|
||||
it "can be one of the user's hats" do
|
||||
user = User.make!
|
||||
hat = Hat.make!(user_id: user.id)
|
||||
comment = Comment.make!(user_id: user.id, hat: hat)
|
||||
hat = create(:hat)
|
||||
user = hat.user
|
||||
comment = create(:comment, user: user, hat: hat)
|
||||
comment.valid?
|
||||
expect(comment.errors[:hat]).to be_empty
|
||||
end
|
||||
|
|
|
@ -2,13 +2,13 @@ require "rails_helper"
|
|||
|
||||
describe EmailParser do
|
||||
before(:each) do
|
||||
@user = User.make!
|
||||
@story = Story.make!(:user => @user)
|
||||
@user = create(:user)
|
||||
@story = create(:story, :user => @user)
|
||||
|
||||
@commentor = User.make!
|
||||
@comment = Comment.make!(:story => @story, :user => @commentor)
|
||||
@commentor = create(:user)
|
||||
@comment = create(:comment, :story => @story, :user => @commentor)
|
||||
|
||||
@emailer = User.make!(:mailing_list_mode => 1)
|
||||
@emailer = create(:user, :mailing_list_mode => 1)
|
||||
|
||||
@emails = {}
|
||||
Dir.glob("#{Rails.root}/spec/fixtures/inbound_emails/*.eml")
|
||||
|
|
|
@ -7,7 +7,7 @@ describe Markdowner do
|
|||
end
|
||||
|
||||
it "turns @username into a link if @username exists" do
|
||||
User.make!(:username => "blahblah")
|
||||
create(:user, :username => "blahblah")
|
||||
|
||||
expect(Markdowner.to_html("hi @blahblah test"))
|
||||
.to eq("<p>hi <a href=\"https://example.com/u/blahblah\" rel=\"nofollow\">" +
|
||||
|
@ -26,7 +26,7 @@ describe Markdowner do
|
|||
|
||||
# bug#242
|
||||
it "does not expand @ signs inside urls" do
|
||||
User.make!(:username => "blahblah")
|
||||
create(:user, :username => "blahblah")
|
||||
|
||||
expect(Markdowner.to_html("hi http://example.com/@blahblah/ test"))
|
||||
.to eq("<p>hi <a href=\"http://example.com/@blahblah/\" rel=\"nofollow\">" +
|
||||
|
|
|
@ -2,21 +2,21 @@ require "rails_helper"
|
|||
|
||||
describe Message do
|
||||
it "should get a short id" do
|
||||
m = Message.make!
|
||||
m = create(:message)
|
||||
expect(m.short_id).to match(/^\A[a-zA-Z0-9]{1,10}\z/)
|
||||
end
|
||||
|
||||
describe "hat" do
|
||||
it "can't be worn if user doesn't have that hat" do
|
||||
message = Message.make(hat: Hat.make!)
|
||||
message = build(:message, hat: create(:hat))
|
||||
message.valid?
|
||||
expect(message.errors[:hat]).to eq(['not wearable by author'])
|
||||
end
|
||||
|
||||
it "can be one of the user's hats" do
|
||||
user = User.make!
|
||||
hat = Hat.make!(user_id: user.id)
|
||||
message = Message.make!(author_user_id: user.id, hat: hat)
|
||||
user = create(:user)
|
||||
hat = create(:hat, user: user)
|
||||
message = create(:message, author: user, hat: hat)
|
||||
message.valid?
|
||||
expect(message.errors[:hat]).to be_empty
|
||||
end
|
||||
|
|
|
@ -6,27 +6,27 @@ describe Search do
|
|||
# the search module uses custom SQL that doesn't
|
||||
# work inside the transaction
|
||||
before(:all) do
|
||||
@user = User.make!
|
||||
@user = create(:user)
|
||||
|
||||
@multi_tag = Story.make!(:title => "multitag term1 t1 t2",
|
||||
@multi_tag = create(:story, :title => "multitag term1 t1 t2",
|
||||
:url => "https://example.com/3",
|
||||
:user_id => @user.id,
|
||||
:tags_a => ["tag1", "tag2"])
|
||||
@stories = [
|
||||
Story.make!(:title => "unique",
|
||||
create(:story, :title => "unique",
|
||||
:url => "https://example.com/unique",
|
||||
:user_id => @user.id,
|
||||
:tags_a => ["tag1"]),
|
||||
Story.make!(:title => "term1 domain1",
|
||||
create(:story, :title => "term1 domain1",
|
||||
:url => "https://example.com/1",
|
||||
:user_id => @user.id,
|
||||
:tags_a => ["tag1"]),
|
||||
Story.make!(:title => "term1 t2",
|
||||
create(:story, :title => "term1 t2",
|
||||
:url => "https://example.com/2",
|
||||
:user_id => @user.id,
|
||||
:tags_a => ["tag2"]),
|
||||
@multi_tag,
|
||||
Story.make!(:title => "term1 domain2",
|
||||
create(:story, :title => "term1 domain2",
|
||||
:url => "https://lobste.rs/1",
|
||||
:user_id => @user.id,
|
||||
:tags_a => ["tag1"]),
|
||||
|
|
|
@ -2,36 +2,38 @@ require "rails_helper"
|
|||
|
||||
describe Story do
|
||||
it "should get a short id" do
|
||||
s = Story.make!(:title => "hello", :url => "http://example.com/")
|
||||
s = create(:story, :title => "hello", :url => "http://example.com/")
|
||||
|
||||
expect(s.short_id).to match(/^\A[a-zA-Z0-9]{1,10}\z/)
|
||||
end
|
||||
|
||||
it "requires a url or a description" do
|
||||
expect { Story.make!(:title => "hello", :url => "", :description => "") }.to raise_error
|
||||
|
||||
expect { Story.make!(:title => "hello", :description => "hi", :url => nil) }.to_not raise_error
|
||||
expect { create(:story, :title => "hello", :url => "", :description => "") }.to raise_error
|
||||
|
||||
expect {
|
||||
Story.make!(:title => "hello", :url => "http://ex.com/", :description => nil)
|
||||
create(:story, :title => "hello", :description => "hi", :url => nil)
|
||||
}.to_not raise_error
|
||||
|
||||
expect {
|
||||
create(:story, :title => "hello", :url => "http://ex.com/", :description => nil)
|
||||
}.to_not raise_error
|
||||
end
|
||||
|
||||
it "does not allow too-short titles" do
|
||||
expect { Story.make!(:title => "") }.to raise_error
|
||||
expect { Story.make!(:title => "hi") }.to raise_error
|
||||
expect { Story.make!(:title => "hello") }.to_not raise_error
|
||||
expect { create(:story, :title => "") }.to raise_error
|
||||
expect { create(:story, :title => "hi") }.to raise_error
|
||||
expect { create(:story, :title => "hello") }.to_not raise_error
|
||||
end
|
||||
|
||||
it "does not allow too-long titles" do
|
||||
expect { Story.make!(:title => ("hello" * 100)) }.to raise_error
|
||||
expect { create(:story, :title => ("hello" * 100)) }.to raise_error
|
||||
end
|
||||
|
||||
it "must have at least one tag" do
|
||||
expect { Story.make!(:tags_a => nil) }.to raise_error
|
||||
expect { Story.make!(:tags_a => ["", " "]) }.to raise_error
|
||||
expect { create(:story, :tags_a => nil) }.to raise_error
|
||||
expect { create(:story, :tags_a => ["", " "]) }.to raise_error
|
||||
|
||||
expect { Story.make!(:tags_a => ["", "tag1"]) }.to_not raise_error
|
||||
expect { create(:story, :tags_a => ["", "tag1"]) }.to_not raise_error
|
||||
end
|
||||
|
||||
it "removes redundant http port 80 and https port 443" do
|
||||
|
@ -58,17 +60,17 @@ describe Story do
|
|||
it "checks for a previously posted story with same url" do
|
||||
expect(Story.count).to eq(0)
|
||||
|
||||
Story.make!(:title => "flim flam", :url => "http://example.com/")
|
||||
create(:story, :title => "flim flam", :url => "http://example.com/")
|
||||
expect(Story.count).to eq(1)
|
||||
|
||||
expect {
|
||||
Story.make!(:title => "flim flam 2", :url => "http://example.com/")
|
||||
create(:story, :title => "flim flam 2", :url => "http://example.com/")
|
||||
}.to raise_error
|
||||
|
||||
expect(Story.count).to eq(1)
|
||||
|
||||
expect {
|
||||
Story.make!(:title => "flim flam 2", :url => "http://www.example.com/")
|
||||
create(:story, :title => "flim flam 2", :url => "http://www.example.com/")
|
||||
}.to raise_error
|
||||
|
||||
expect(Story.count).to eq(1)
|
||||
|
@ -90,7 +92,7 @@ describe Story do
|
|||
end
|
||||
|
||||
it "has domain straight out of the db, when Rails doesn't use setters" do
|
||||
s = Story.make!(url: 'https://example.com/foo.html')
|
||||
s = create(:story, url: 'https://example.com/foo.html')
|
||||
s = Story.find(s.id)
|
||||
expect(s.domain).to eq('example.com')
|
||||
s.url = 'http://example.org'
|
||||
|
@ -100,35 +102,33 @@ describe Story do
|
|||
end
|
||||
|
||||
it "converts a title to a url properly" do
|
||||
s = Story.make!(:title => "Hello there, this is a title")
|
||||
s = create(:story, :title => "Hello there, this is a title")
|
||||
expect(s.title_as_url).to eq("hello_there_this_is_title")
|
||||
|
||||
s = Story.make!(:title => "Hello _ underscore")
|
||||
s = create(:story, :title => "Hello _ underscore")
|
||||
expect(s.title_as_url).to eq("hello_underscore")
|
||||
|
||||
s = Story.make!(:title => "Hello, underscore")
|
||||
s = create(:story, :title => "Hello, underscore")
|
||||
expect(s.title_as_url).to eq("hello_underscore")
|
||||
|
||||
s = Story.make(:title => "The One-second War (What Time Will You Die?) ")
|
||||
s = build(:story, :title => "The One-second War (What Time Will You Die?) ")
|
||||
expect(s.title_as_url).to eq("one_second_war_what_time_will_you_die")
|
||||
end
|
||||
|
||||
it "is not editable by another non-admin user" do
|
||||
u = User.make!
|
||||
s = create(:story)
|
||||
expect(s.is_editable_by_user?(s.user)).to be true
|
||||
|
||||
s = Story.make!(:user_id => u.id)
|
||||
expect(s.is_editable_by_user?(u)).to be true
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
expect(s.is_editable_by_user?(u)).to be false
|
||||
end
|
||||
|
||||
it "can fetch its title properly" do
|
||||
s = Story.make
|
||||
s = build(:story)
|
||||
s.fetched_content = File.read(Rails.root + "spec/fixtures/story_pages/1.html")
|
||||
expect(s.fetched_attributes[:title]).to eq("B2G demo & quick hack // by Paul Rouget")
|
||||
|
||||
s = Story.make
|
||||
s = build(:story)
|
||||
s.fetched_content = File.read(Rails.root + "spec/fixtures/story_pages/2.html")
|
||||
expect(s.fetched_attributes[:title]).to eq("Google")
|
||||
end
|
||||
|
@ -140,23 +140,23 @@ describe Story do
|
|||
end
|
||||
|
||||
it "sets the url properly" do
|
||||
s = Story.make(:title => "blah")
|
||||
s = build(:story, :title => "blah")
|
||||
s.url = "https://factorable.net/"
|
||||
s.valid?
|
||||
expect(s.url).to eq("https://factorable.net/")
|
||||
end
|
||||
|
||||
it "calculates tag changes properly" do
|
||||
s = Story.make!(:title => "blah", :tags_a => ["tag1", "tag2"])
|
||||
s = create(:story, :title => "blah", :tags_a => ["tag1", "tag2"])
|
||||
|
||||
s.tags_a = ["tag2"]
|
||||
expect(s.tagging_changes).to eq("tags" => ["tag1 tag2", "tag2"])
|
||||
end
|
||||
|
||||
it "logs moderations properly" do
|
||||
mod = User.make!(:username => "mod", :is_moderator => true)
|
||||
mod = create(:user, :moderator)
|
||||
|
||||
s = Story.make!(:title => "blah", :tags_a => ["tag1", "tag2"],
|
||||
s = create(:story, :title => "blah", :tags_a => ["tag1", "tag2"],
|
||||
:description => "desc")
|
||||
|
||||
s.title = "changed title"
|
||||
|
|
|
@ -2,26 +2,26 @@ require "rails_helper"
|
|||
|
||||
describe User do
|
||||
it "has a valid username" do
|
||||
expect { User.make!(:username => nil) }.to raise_error
|
||||
expect { User.make!(:username => "") }.to raise_error
|
||||
expect { User.make!(:username => "*") }.to raise_error
|
||||
expect { create(:user, :username => nil) }.to raise_error
|
||||
expect { create(:user, :username => "") }.to raise_error
|
||||
expect { create(:user, :username => "*") }.to raise_error
|
||||
|
||||
User.make!(:username => "newbie")
|
||||
expect { User.make!(:username => "newbie") }.to raise_error
|
||||
create(:user, :username => "newbie")
|
||||
expect { create(:user, :username => "newbie") }.to raise_error
|
||||
end
|
||||
|
||||
it "has a valid email address" do
|
||||
User.make!(:email => "user@example.com")
|
||||
create(:user, :email => "user@example.com")
|
||||
|
||||
# duplicate
|
||||
expect { User.make!(:email => "user@example.com") }.to raise_error
|
||||
expect { create(:user, :email => "user@example.com") }.to raise_error
|
||||
|
||||
# bad address
|
||||
expect { User.make!(:email => "user@") }.to raise_error
|
||||
expect { create(:user, :email => "user@") }.to raise_error
|
||||
end
|
||||
|
||||
it "authenticates properly" do
|
||||
u = User.make!(:password => "hunter2")
|
||||
u = create(:user, :password => "hunter2")
|
||||
|
||||
expect(u.password_digest.length).to be > 20
|
||||
|
||||
|
@ -30,57 +30,57 @@ describe User do
|
|||
end
|
||||
|
||||
it "gets an error message after registering banned name" do
|
||||
expect { User.make!(:username => "admin") }
|
||||
expect { create(:user, :username => "admin") }
|
||||
.to raise_error("Validation failed: Username is not permitted")
|
||||
end
|
||||
|
||||
it "shows a user is banned or not" do
|
||||
u = User.make!(:banned)
|
||||
user = User.make!
|
||||
u = create(:user, :banned)
|
||||
user = create(:user)
|
||||
expect(u.is_banned?).to be true
|
||||
expect(user.is_banned?).to be false
|
||||
end
|
||||
|
||||
it "shows a user is active or not" do
|
||||
u = User.make!(:banned)
|
||||
user = User.make!
|
||||
u = create(:user, :banned)
|
||||
user = create(:user)
|
||||
expect(u.is_active?).to be false
|
||||
expect(user.is_active?).to be true
|
||||
end
|
||||
|
||||
it "shows a user is recent or not" do
|
||||
user = User.make!(:created_at => Time.current)
|
||||
u = User.make!(:created_at => Time.current - 8.days)
|
||||
user = create(:user, :created_at => Time.current)
|
||||
u = create(:user, :created_at => Time.current - 8.days)
|
||||
expect(user.is_new?).to be true
|
||||
expect(u.is_new?).to be false
|
||||
end
|
||||
|
||||
it "unbans a user" do
|
||||
u = User.make!(:banned)
|
||||
u = create(:user, :banned)
|
||||
expect(u.unban_by_user!(User.first)).to be true
|
||||
end
|
||||
|
||||
it "tells if a user is a heavy self promoter" do
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
expect(u.is_heavy_self_promoter?).to be false
|
||||
|
||||
Story.make!(:title => "ti1", :url => "https://a.com/1", :user_id => u.id,
|
||||
create(:story, :title => "ti1", :url => "https://a.com/1", :user_id => u.id,
|
||||
:user_is_author => true)
|
||||
# require at least 2 stories to be considered heavy self promoter
|
||||
expect(u.is_heavy_self_promoter?).to be false
|
||||
|
||||
Story.make!(:title => "ti2", :url => "https://a.com/2", :user_id => u.id,
|
||||
create(:story, :title => "ti2", :url => "https://a.com/2", :user_id => u.id,
|
||||
:user_is_author => true)
|
||||
# 100% of 2 stories
|
||||
expect(u.is_heavy_self_promoter?).to be true
|
||||
|
||||
Story.make!(:title => "ti3", :url => "https://a.com/3", :user_id => u.id,
|
||||
create(:story, :title => "ti3", :url => "https://a.com/3", :user_id => u.id,
|
||||
:user_is_author => false)
|
||||
# 66.7% of 3 stories
|
||||
expect(u.is_heavy_self_promoter?).to be true
|
||||
|
||||
Story.make!(:title => "ti4", :url => "https://a.com/4", :user_id => u.id,
|
||||
create(:story, :title => "ti4", :url => "https://a.com/4", :user_id => u.id,
|
||||
:user_is_author => false)
|
||||
# 50% of 4 stories
|
||||
expect(u.is_heavy_self_promoter?).to be false
|
||||
|
|
|
@ -2,13 +2,12 @@ require "rails_helper"
|
|||
|
||||
describe Vote do
|
||||
it "applies a story upvote and karma properly" do
|
||||
s = Story.make!
|
||||
|
||||
s = create(:story)
|
||||
expect(s.upvotes).to eq(1)
|
||||
expect(s.downvotes).to eq(0)
|
||||
expect(s.user.karma).to eq(0)
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
Vote.vote_thusly_on_story_or_comment_for_user_because(1, s.id, nil, u.id, nil)
|
||||
|
||||
|
@ -19,9 +18,9 @@ describe Vote do
|
|||
end
|
||||
|
||||
it "does nothing when upvoting an existing upvote" do
|
||||
s = Story.make!
|
||||
s = create(:story)
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
2.times do
|
||||
Vote.vote_thusly_on_story_or_comment_for_user_because(1, s.id, nil, u.id, nil)
|
||||
|
@ -34,10 +33,10 @@ describe Vote do
|
|||
end
|
||||
|
||||
it "has no effect on a story score when casting a hide vote" do
|
||||
s = Story.make!
|
||||
s = create(:story)
|
||||
expect(s.upvotes).to eq(1)
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
Vote.vote_thusly_on_story_or_comment_for_user_because(0, s.id, nil, u.id, "H")
|
||||
s.reload
|
||||
|
@ -47,11 +46,11 @@ describe Vote do
|
|||
end
|
||||
|
||||
it "removes karma and upvote when downvoting an upvote" do
|
||||
s = Story.make!
|
||||
c = Comment.make!(:story_id => s.id)
|
||||
s = create(:story)
|
||||
c = create(:comment, :story => s)
|
||||
expect(c.user.karma).to eq(0)
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
Vote.vote_thusly_on_story_or_comment_for_user_because(1, s.id, c.id, u.id, nil)
|
||||
c.reload
|
||||
|
@ -72,10 +71,10 @@ describe Vote do
|
|||
end
|
||||
|
||||
it "neutralizes karma and upvote when unvoting an upvote" do
|
||||
s = Story.make!
|
||||
c = Comment.make!(:story_id => s.id)
|
||||
s = create(:story)
|
||||
c = create(:comment, :story_id => s.id)
|
||||
|
||||
u = User.make!
|
||||
u = create(:user)
|
||||
|
||||
Vote.vote_thusly_on_story_or_comment_for_user_because(1, s.id, c.id, u.id, nil)
|
||||
c.reload
|
||||
|
|
|
@ -7,6 +7,9 @@ require 'rspec/rails'
|
|||
# in spec/support/ and its subdirectories.
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f }
|
||||
|
||||
Tag.destroy_all
|
||||
Tag.create!([{ tag: "tag1" }, { tag: "tag2" }])
|
||||
|
||||
RSpec.configure do |config|
|
||||
# ## Mock Framework
|
||||
#
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
require 'machinist/active_record'
|
||||
|
||||
User.blueprint do
|
||||
email { "user-#{sn}@example.com" }
|
||||
password { "blah blah" }
|
||||
password_confirmation { object.password }
|
||||
username { "username#{sn}" }
|
||||
is_moderator { false }
|
||||
is_admin { false }
|
||||
end
|
||||
|
||||
User.blueprint(:banned) do
|
||||
email { "banned-#{sn}@example.com" }
|
||||
password { "blah blah" }
|
||||
password_confirmation { object.password }
|
||||
username { "username#{sn}" }
|
||||
banned_at { Time.current }
|
||||
end
|
||||
|
||||
Tag.blueprint do
|
||||
tag { "tag-#{sn}" }
|
||||
description { "tag #{sn}" }
|
||||
end
|
||||
|
||||
# these need to exist for stories to use them
|
||||
Tag.destroy_all
|
||||
Tag.make!(:tag => "tag1")
|
||||
Tag.make!(:tag => "tag2")
|
||||
|
||||
Story.blueprint do
|
||||
user_id { User.make!.id }
|
||||
title { "story title #{sn}" }
|
||||
url { "http://example.com/#{sn}" }
|
||||
tags_a { ["tag1", "tag2"] }
|
||||
end
|
||||
|
||||
Hat.blueprint do
|
||||
user_id { User.make!.id }
|
||||
hat { "hat #{rand}" }
|
||||
granted_by_user_id { User.make!.id }
|
||||
link { 'http://example.com' }
|
||||
end
|
||||
|
||||
Comment.blueprint do
|
||||
user_id { User.make!.id }
|
||||
story_id { Story.make!.id }
|
||||
comment { "comment text #{sn}" }
|
||||
hat { nil }
|
||||
created_at { Time.current }
|
||||
end
|
||||
|
||||
Message.blueprint do
|
||||
recipient_user_id { User.make!.id }
|
||||
author_user_id { User.make!.id }
|
||||
subject { "message subject #{sn}" }
|
||||
body { "message body #{sn}" }
|
||||
hat { nil }
|
||||
end
|
||||
|
||||
Vote.blueprint do
|
||||
story
|
||||
user
|
||||
vote { 1 }
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
RSpec.configure do |config|
|
||||
config.include FactoryBot::Syntax::Methods
|
||||
end
|
Loading…
Reference in New Issue