@@ -70,6 +70,7 @@ group :test do | |||||
gem 'simplecov', require: false | gem 'simplecov', require: false | ||||
gem 'webmock' | gem 'webmock' | ||||
gem 'rspec-sidekiq' | gem 'rspec-sidekiq' | ||||
gem 'faker' | |||||
end | end | ||||
group :development do | group :development do | ||||
@@ -149,6 +149,8 @@ GEM | |||||
erubis (2.7.0) | erubis (2.7.0) | ||||
execjs (2.7.0) | execjs (2.7.0) | ||||
fabrication (2.15.2) | fabrication (2.15.2) | ||||
faker (1.6.6) | |||||
i18n (~> 0.5) | |||||
fast_blank (1.0.0) | fast_blank (1.0.0) | ||||
font-awesome-rails (4.6.3.1) | font-awesome-rails (4.6.3.1) | ||||
railties (>= 3.2, < 5.1) | railties (>= 3.2, < 5.1) | ||||
@@ -470,6 +472,7 @@ DEPENDENCIES | |||||
doorkeeper | doorkeeper | ||||
dotenv-rails | dotenv-rails | ||||
fabrication | fabrication | ||||
faker | |||||
fast_blank | fast_blank | ||||
font-awesome-rails | font-awesome-rails | ||||
fuubar | fuubar | ||||
@@ -3,9 +3,8 @@ | |||||
class Block < ApplicationRecord | class Block < ApplicationRecord | ||||
include Paginable | include Paginable | ||||
belongs_to :account | |||||
belongs_to :target_account, class_name: 'Account' | |||||
belongs_to :account, required: true | |||||
belongs_to :target_account, class_name: 'Account', required: true | |||||
validates :account, :target_account, presence: true | |||||
validates :account_id, uniqueness: { scope: :target_account_id } | validates :account_id, uniqueness: { scope: :target_account_id } | ||||
end | end |
@@ -3,11 +3,14 @@ | |||||
class Follow < ApplicationRecord | class Follow < ApplicationRecord | ||||
include Paginable | include Paginable | ||||
belongs_to :account, counter_cache: :following_count | |||||
belongs_to :target_account, class_name: 'Account', counter_cache: :followers_count | |||||
belongs_to :account, counter_cache: :following_count, required: true | |||||
belongs_to :target_account, | |||||
class_name: 'Account', | |||||
counter_cache: :followers_count, | |||||
required: true | |||||
has_one :notification, as: :activity, dependent: :destroy | has_one :notification, as: :activity, dependent: :destroy | ||||
validates :account, :target_account, presence: true | |||||
validates :account_id, uniqueness: { scope: :target_account_id } | validates :account_id, uniqueness: { scope: :target_account_id } | ||||
end | end |
@@ -3,12 +3,11 @@ | |||||
class FollowRequest < ApplicationRecord | class FollowRequest < ApplicationRecord | ||||
include Paginable | include Paginable | ||||
belongs_to :account | |||||
belongs_to :target_account, class_name: 'Account' | |||||
belongs_to :account, required: true | |||||
belongs_to :target_account, class_name: 'Account', required: true | |||||
has_one :notification, as: :activity, dependent: :destroy | has_one :notification, as: :activity, dependent: :destroy | ||||
validates :account, :target_account, presence: true | |||||
validates :account_id, uniqueness: { scope: :target_account_id } | validates :account_id, uniqueness: { scope: :target_account_id } | ||||
def authorize! | def authorize! | ||||
@@ -1,11 +1,10 @@ | |||||
# frozen_string_literal: true | # frozen_string_literal: true | ||||
class Mention < ApplicationRecord | class Mention < ApplicationRecord | ||||
belongs_to :account, inverse_of: :mentions | |||||
belongs_to :status | |||||
belongs_to :account, inverse_of: :mentions, required: true | |||||
belongs_to :status, required: true | |||||
has_one :notification, as: :activity, dependent: :destroy | has_one :notification, as: :activity, dependent: :destroy | ||||
validates :account, :status, presence: true | |||||
validates :account, uniqueness: { scope: :status } | validates :account, uniqueness: { scope: :status } | ||||
end | end |
@@ -3,6 +3,10 @@ default: &default | |||||
pool: <%= ENV["DB_POOL"] || ENV['MAX_THREADS'] || 5 %> | pool: <%= ENV["DB_POOL"] || ENV['MAX_THREADS'] || 5 %> | ||||
timeout: 5000 | timeout: 5000 | ||||
encoding: unicode | encoding: unicode | ||||
host: localhost | |||||
username: samy | |||||
password: tardis | |||||
port: 32769 | |||||
development: | development: | ||||
<<: *default | <<: *default | ||||
@@ -1,3 +1,3 @@ | |||||
Fabricator(:account) do | Fabricator(:account) do | ||||
username "alice" | |||||
username { Faker::Internet.user_name(nil, %w(_)) } | |||||
end | end |
@@ -1,3 +1,4 @@ | |||||
Fabricator(:block) do | Fabricator(:block) do | ||||
account | |||||
target_account { Fabricate(:account) } | |||||
end | end |
@@ -1,3 +1,4 @@ | |||||
Fabricator(:follow) do | Fabricator(:follow) do | ||||
account | |||||
target_account { Fabricate(:account) } | |||||
end | end |
@@ -1,3 +1,4 @@ | |||||
Fabricator(:follow_request) do | Fabricator(:follow_request) do | ||||
account | |||||
target_account { Fabricate(:account) } | |||||
end | end |
@@ -0,0 +1,4 @@ | |||||
Fabricator(:mention) do | |||||
account | |||||
status | |||||
end |
@@ -1,6 +1,6 @@ | |||||
Fabricator(:user) do | Fabricator(:user) do | ||||
account | account | ||||
email "alice@example.com" | |||||
email { Faker::Internet.email } | |||||
password "123456789" | password "123456789" | ||||
confirmed_at { Time.now } | confirmed_at { Time.now } | ||||
end | end |
@@ -209,4 +209,73 @@ RSpec.describe Account, type: :model do | |||||
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil | expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil | ||||
end | end | ||||
end | end | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
account = Fabricate.build(:account) | |||||
account.valid? | |||||
expect(account).to be_valid | |||||
end | |||||
it 'is invalid without a username' do | |||||
account = Fabricate.build(:account, username: nil) | |||||
account.valid? | |||||
expect(account).to model_have_error_on_field(:username) | |||||
end | |||||
it 'is invalid is the username already exists' do | |||||
account_1 = Fabricate(:account, username: 'the_doctor') | |||||
account_2 = Fabricate.build(:account, username: 'the_doctor') | |||||
account_2.valid? | |||||
expect(account_2).to model_have_error_on_field(:username) | |||||
end | |||||
context 'when is local' do | |||||
it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do | |||||
account = Fabricate.build(:account, username: 'the-doctor') | |||||
account.valid? | |||||
expect(account).to model_have_error_on_field(:username) | |||||
end | |||||
it 'is invalid if the username is longer then 30 characters' do | |||||
account = Fabricate.build(:account, username: Faker::Lorem.characters(31)) | |||||
account.valid? | |||||
expect(account).to model_have_error_on_field(:username) | |||||
end | |||||
end | |||||
end | |||||
describe 'scopes' do | |||||
describe 'remote' do | |||||
it 'returns an array of accounts who have a domain' do | |||||
account_1 = Fabricate(:account, domain: nil) | |||||
account_2 = Fabricate(:account, domain: 'example.com') | |||||
expect(Account.remote).to match_array([account_2]) | |||||
end | |||||
end | |||||
describe 'local' do | |||||
it 'returns an array of accounts who do not have a domain' do | |||||
account_1 = Fabricate(:account, domain: nil) | |||||
account_2 = Fabricate(:account, domain: 'example.com') | |||||
expect(Account.local).to match_array([account_1]) | |||||
end | |||||
end | |||||
describe 'silenced' do | |||||
it 'returns an array of accounts who are silenced' do | |||||
account_1 = Fabricate(:account, silenced: true) | |||||
account_2 = Fabricate(:account, silenced: false) | |||||
expect(Account.silenced).to match_array([account_1]) | |||||
end | |||||
end | |||||
describe 'suspended' do | |||||
it 'returns an array of accounts who are suspended' do | |||||
account_1 = Fabricate(:account, suspended: true) | |||||
account_2 = Fabricate(:account, suspended: false) | |||||
expect(Account.suspended).to match_array([account_1]) | |||||
end | |||||
end | |||||
end | |||||
end | end |
@@ -1,5 +1,22 @@ | |||||
require 'rails_helper' | require 'rails_helper' | ||||
RSpec.describe Block, type: :model do | RSpec.describe Block, type: :model do | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
block = Fabricate.build(:block) | |||||
expect(block).to be_valid | |||||
end | |||||
it 'is invalid without an account' do | |||||
block = Fabricate.build(:block, account: nil) | |||||
block.valid? | |||||
expect(block).to model_have_error_on_field(:account) | |||||
end | |||||
it 'is invalid without a target_account' do | |||||
block = Fabricate.build(:block, target_account: nil) | |||||
block.valid? | |||||
expect(block).to model_have_error_on_field(:target_account) | |||||
end | |||||
end | |||||
end | end |
@@ -1,5 +1,23 @@ | |||||
require 'rails_helper' | require 'rails_helper' | ||||
RSpec.describe DomainBlock, type: :model do | RSpec.describe DomainBlock, type: :model do | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
domain_block = Fabricate.build(:domain_block) | |||||
expect(domain_block).to be_valid | |||||
end | |||||
it 'is invalid without a domain' do | |||||
domain_block = Fabricate.build(:domain_block, domain: nil) | |||||
domain_block.valid? | |||||
expect(domain_block).to model_have_error_on_field(:domain) | |||||
end | |||||
it 'is invalid if the domain already exists' do | |||||
domain_block_1 = Fabricate(:domain_block, domain: 'dalek.com') | |||||
domain_block_2 = Fabricate.build(:domain_block, domain: 'dalek.com') | |||||
domain_block_2.valid? | |||||
expect(domain_block_2).to model_have_error_on_field(:domain) | |||||
end | |||||
end | |||||
end | end |
@@ -3,4 +3,23 @@ require 'rails_helper' | |||||
RSpec.describe FollowRequest, type: :model do | RSpec.describe FollowRequest, type: :model do | ||||
describe '#authorize!' | describe '#authorize!' | ||||
describe '#reject!' | describe '#reject!' | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
follow_request = Fabricate.build(:follow_request) | |||||
expect(follow_request).to be_valid | |||||
end | |||||
it 'is invalid without an account' do | |||||
follow_request = Fabricate.build(:follow_request, account: nil) | |||||
follow_request.valid? | |||||
expect(follow_request).to model_have_error_on_field(:account) | |||||
end | |||||
it 'is invalid without a target account' do | |||||
follow_request = Fabricate.build(:follow_request, target_account: nil) | |||||
follow_request.valid? | |||||
expect(follow_request).to model_have_error_on_field(:target_account) | |||||
end | |||||
end | |||||
end | end |
@@ -5,4 +5,23 @@ RSpec.describe Follow, type: :model do | |||||
let(:bob) { Fabricate(:account, username: 'bob') } | let(:bob) { Fabricate(:account, username: 'bob') } | ||||
subject { Follow.new(account: alice, target_account: bob) } | subject { Follow.new(account: alice, target_account: bob) } | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
follow = Fabricate.build(:follow) | |||||
expect(follow).to be_valid | |||||
end | |||||
it 'is invalid without an account' do | |||||
follow = Fabricate.build(:follow, account: nil) | |||||
follow.valid? | |||||
expect(follow).to model_have_error_on_field(:account) | |||||
end | |||||
it 'is invalid without a target_account' do | |||||
follow = Fabricate.build(:follow, target_account: nil) | |||||
follow.valid? | |||||
expect(follow).to model_have_error_on_field(:target_account) | |||||
end | |||||
end | |||||
end | end |
@@ -1,5 +1,22 @@ | |||||
require 'rails_helper' | require 'rails_helper' | ||||
RSpec.describe Mention, type: :model do | RSpec.describe Mention, type: :model do | ||||
describe 'validations' do | |||||
it 'has a valid fabricator' do | |||||
mention = Fabricate.build(:mention) | |||||
expect(mention).to be_valid | |||||
end | |||||
it 'is invalid without an account' do | |||||
mention = Fabricate.build(:mention, account: nil) | |||||
mention.valid? | |||||
expect(mention).to model_have_error_on_field(:account) | |||||
end | |||||
it 'is invalid without a status' do | |||||
mention = Fabricate.build(:mention, status: nil) | |||||
mention.valid? | |||||
expect(mention).to model_have_error_on_field(:status) | |||||
end | |||||
end | |||||
end | end |
@@ -1,5 +1,49 @@ | |||||
require 'rails_helper' | require 'rails_helper' | ||||
RSpec.describe User, type: :model do | RSpec.describe User, type: :model do | ||||
describe 'validations' do | |||||
it 'is invalid without an account' do | |||||
user = Fabricate.build(:user, account: nil) | |||||
user.valid? | |||||
expect(user).to model_have_error_on_field(:account) | |||||
end | |||||
it 'is invalid without a valid locale' do | |||||
user = Fabricate.build(:user, locale: 'toto') | |||||
user.valid? | |||||
expect(user).to model_have_error_on_field(:locale) | |||||
end | |||||
it 'is invalid without a valid email' do | |||||
user = Fabricate.build(:user, email: 'john@') | |||||
user.valid? | |||||
expect(user).to model_have_error_on_field(:email) | |||||
end | |||||
end | |||||
describe 'scopes' do | |||||
describe 'recent' do | |||||
it 'returns an array of recent users ordered by id' do | |||||
user_1 = Fabricate(:user) | |||||
user_2 = Fabricate(:user) | |||||
expect(User.recent).to match_array([user_2, user_1]) | |||||
end | |||||
end | |||||
describe 'admins' do | |||||
it 'returns an array of users who are admin' do | |||||
user_1 = Fabricate(:user, admin: false) | |||||
user_2 = Fabricate(:user, admin: true) | |||||
expect(User.admins).to match_array([user_2]) | |||||
end | |||||
end | |||||
describe 'confirmed' do | |||||
it 'returns an array of users who are confirmed' do | |||||
user_1 = Fabricate(:user, confirmed_at: nil) | |||||
user_2 = Fabricate(:user, confirmed_at: Time.now) | |||||
expect(User.confirmed).to match_array([user_2]) | |||||
end | |||||
end | |||||
end | |||||
end | end |
@@ -8,6 +8,8 @@ require 'rspec/rails' | |||||
require 'webmock/rspec' | require 'webmock/rspec' | ||||
require 'paperclip/matchers' | require 'paperclip/matchers' | ||||
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } | |||||
ActiveRecord::Migration.maintain_test_schema! | ActiveRecord::Migration.maintain_test_schema! | ||||
WebMock.disable_net_connect!(allow: 'localhost:7575') | WebMock.disable_net_connect!(allow: 'localhost:7575') | ||||
Sidekiq::Testing.inline! | Sidekiq::Testing.inline! | ||||
@@ -0,0 +1,15 @@ | |||||
RSpec::Matchers.define :model_have_error_on_field do |expected| | |||||
match do |record| | |||||
if record.errors.empty? | |||||
record.valid? | |||||
end | |||||
record.errors.has_key?(expected) | |||||
end | |||||
failure_message do |record| | |||||
keys = record.errors.keys | |||||
"expect record.errors(#{keys}) to include #{expected}" | |||||
end | |||||
end |