diff --git a/app/models/user.rb b/app/models/user.rb index cee87c8..e67bdfa 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,7 +1,7 @@ class User < ApplicationRecord # -- Validations validates :email, presence: true, uniqueness: true - validates :password, presence: true, length: {minimum: 8} + validates :password, presence: true, length: { minimum: 8 } validates :role, presence: true # -- Associations diff --git a/spec/factories/posts.rb b/spec/factories/posts.rb index 402d675..c335d6b 100644 --- a/spec/factories/posts.rb +++ b/spec/factories/posts.rb @@ -1,3 +1,7 @@ FactoryBot.define do - # Implementar factory + factory :post do + association :user + title { Faker::Lorem.unique.word } + body { Faker::Lorem.sentence(30) } + end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 72d97d1..f4e0b16 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :user do auth_token { SecureRandom.hex } - email { Faker::Internet.email } + email { Faker::Internet.unique.email } password { SecureRandom.uuid } # Definición de atributos transitorios o transients diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 2162433..f7dbc77 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -3,4 +3,26 @@ RSpec.describe Post, type: :model do # En base al modelo de test propuesto para el modelo User, # implementar los tests para el modelo Post. + describe 'Factory' do + it 'has a valid factory' do + expect(build(:post)).to be_valid + end + end + + describe 'Associations' do + it { should belong_to(:user) } + # https://github.com/thoughtbot/shoulda-matchers#activerecord-matchers + end + + describe 'Presence validations' do + it { should validate_presence_of(:title) } + it { should validate_presence_of(:body) } + # https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers + end + + describe 'Uniqueness validations' do + subject { create(:post) } + it { should validate_uniqueness_of(:title) } + # https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 4db8f67..a040a81 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -3,37 +3,51 @@ RSpec.describe User, type: :model do describe 'Factory' do it 'has a valid factory' do - # Testear que el factory definido es válido. + expect(build(:user)).to be_valid end end describe 'Associations' do - # Testear asociaciones (shoulda-matchers). + it { should have_many(:posts) } # https://github.com/thoughtbot/shoulda-matchers#activerecord-matchers end describe 'Presence validations' do - # Testear validaciones de presencia (shoulda-matchers). + it { should validate_presence_of(:email) } + it { should validate_presence_of(:password) } + it { should validate_presence_of(:role) } # https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers end describe 'Uniqueness validations' do - # Testear validaciones de unicidad (shoulda-matchers). + subject { create(:user) } + it { should validate_uniqueness_of(:email) } # https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers end describe 'Length validations' do - # Testear validaciones de longitud (shoulda-matchers). + it { should validate_length_of(:password).is_at_least(8) } # https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers end describe 'Enumeratives' do - # Testear definición de enumerativos (shoulda-matchers). + it { should define_enum_for(:role) } end - # Testear métodos de instancia y de clase como para el caso de cualquier - # otra clase Ruby (similar a testear ApiLoginManager). describe '#valid_password?' do + subject { create(:user) } + context 'when given value is different from password' do + it 'returns false' do + expect(subject.valid_password?(SecureRandom.uuid)).to be_falsey + end + end + + context 'when given value is equal to password' do + it 'returns true' do + expect(subject.valid_password?(subject.password)).to be + end + end + # Testear funcionamiento de método. Podemos definir dos contexts: # - 'when given value is different from password' # - 'when given value is equal to password' diff --git a/spec/services/api_login_manager_spec.rb b/spec/services/api_login_manager_spec.rb index 5ea0316..05447a1 100644 --- a/spec/services/api_login_manager_spec.rb +++ b/spec/services/api_login_manager_spec.rb @@ -11,11 +11,12 @@ # en let!(:user) { ... }, usar esta variable. let!(:password) { SecureRandom.hex } - let!(:user) { } # -- crear usuario con FactoryBot -- # + let!(:user) { create(:user, password: password) } # -- crear usuario con FactoryBot -- # describe '#call' do context 'when user provided data is valid' do before do + allow(ExternalValidator).to receive(:call).and_return(true) # Realizar un stub del ExternalValidator para que se ejecuta realmente end @@ -24,60 +25,87 @@ end it "update user's auth_token" do - skip 'Una vez que definan a user, este test va a fallar. ¿Por qué?' - expect { subject }.to change { user.auth_token } + expect { subject }.to change { user.reload.auth_token } end it 'returns the auth_token' do - skip 'Implementar' + expect(subject).to eq(user.reload.auth_token) end end context 'when no email is provided' do - subject { } # implementar + subject { described_class.new(password: password) } it 'returns false' do - skip 'Implementar' + expect(subject.call).to be_falsey end it 'returns EMPTY_EMAIL error with a reader' do - skip 'Implementar' + subject.call + expect(subject.error).to be(ApiLoginManager::EMPTY_EMAIL) end end context 'when no password is provided' do - subject { } # implementar + subject { described_class.new(email: user.email) } it 'returns false' do - skip 'Implementar' + expect(subject.call).to be_falsey end it 'returns EMPTY_PASSWORD error with a reader' do - skip 'Implementar' + subject.call + expect(subject.error).to be(ApiLoginManager::EMPTY_PASSWORD) end end context 'when the email is incorrect' do - subject { } # implementar + subject do + described_class.new( + email: Faker::Internet.unique.email, + password: user.password + ) + end it 'returns false' do - skip 'Implementar' + expect(subject.call).to be_falsey end it 'returns USER_NOT_FOUND error with a reader' do - skip 'Implementar' + subject.call + expect(subject.error).to be(ApiLoginManager::USER_NOT_FOUND) end end context 'when the password is incorrect' do - subject { } # implementar + subject do + described_class.new(email: user.email, password: SecureRandom.uuid) + end it 'returns false' do - skip 'Implementar' + expect(subject.call).to be_falsey end it 'returns WRONG_PASSWORD error with a reader' do - skip 'Implementar' + subject.call + expect(subject.error).to be(ApiLoginManager::WRONG_PASSWORD) + end + end + + context 'when ExternalValidator fails' do + before do + allow(ExternalValidator).to receive(:call).and_return(false) + end + + subject { described_class.new(email: user.email, password: user.password) } + + it 'returns false' do + expect(subject.call).to be_falsey + end + + it 'returns EXTERNAL_VALIDATOR error with a reader' do + subject.call + expect(subject.error).to be(ApiLoginManager::EXTERNAL_VALIDATOR) end end