Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
14 changes: 13 additions & 1 deletion spec/factories/posts.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
FactoryBot.define do
# Implementar factory
factory :post do
title { Faker::Lorem.sentence }
body { Faker::Lorem.paragraph }
association :user

factory :admin_user_post do
user { create(:admin_user) }
end

factory :regular_user_post do
user { create(:regular_user) }
end
end
end
4 changes: 2 additions & 2 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FactoryBot.define do
factory :user do
auth_token { SecureRandom.hex }
email { Faker::Internet.email }
password { SecureRandom.uuid }
email { Faker::Internet.email }
password { SecureRandom.uuid }

# Definición de atributos transitorios o transients
transient do
Expand Down
29 changes: 27 additions & 2 deletions spec/models/post_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
require 'rails_helper'

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(create(:post)).to be_valid
end
end

describe 'Associations' do
it 'belong to an user' do
expect belong_to(:user)
end
end

describe 'Presence validations' do
it 'has a not empty title' do
expect validate_presence_of(:title)
end

it 'has a not empty body' do
expect validate_presence_of(:body)
end
end

describe 'Uniqueness validations' do
it 'has a unique title' do
expect validate_uniqueness_of(:title)
end
end
Comment thread
JulianPasquale marked this conversation as resolved.
end
76 changes: 61 additions & 15 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,85 @@
RSpec.describe User, type: :model do
describe 'Factory' do
it 'has a valid factory' do
# Testear que el factory definido es válido.
expect(create(:user)).to be_valid
end
end

describe 'Associations' do
# Testear asociaciones (shoulda-matchers).
# https://github.com/thoughtbot/shoulda-matchers#activerecord-matchers
it 'has many posts' do
expect have_many(:posts)
Comment thread
JulianPasquale marked this conversation as resolved.
end
end

describe 'Presence validations' do
# Testear validaciones de presencia (shoulda-matchers).
# https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers
it 'has a not empty password' do
expect validate_presence_of(:password)
end

it 'has a not empty email' do
expect validate_presence_of(:email)
end

it 'has a not empty role' do
expect validate_presence_of(:role)
end
end

describe 'Uniqueness validations' do
# Testear validaciones de unicidad (shoulda-matchers).
# https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers
it 'has a unique email' do
expect validate_uniqueness_of(:email)
end
end

describe 'Length validations' do
# Testear validaciones de longitud (shoulda-matchers).
# https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers
it 'has a valid length' do
expect validate_length_of(:password).is_at_least(8)
end
end

describe 'Enumeratives' do
# Testear definición de enumerativos (shoulda-matchers).
it 'has a role enum' do
expect define_enum_for(:role).with([:admin, :regular])
end

describe 'when user is admin' do
Comment thread
JulianPasquale marked this conversation as resolved.
subject do
create(:admin_user)
end

it 'has an admin role' do
expect(subject.admin?).to be true
end
end

describe 'when user is regular' do
Comment thread
JulianPasquale marked this conversation as resolved.
subject do
create(:regular_user)
end

it 'has a regular role' do
expect(subject.regular?).to be true
end
end
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
# Testear funcionamiento de método. Podemos definir dos contexts:
# - 'when given value is different from password'
# - 'when given value is equal to password'
let!(:password) { SecureRandom.hex }
Comment thread
JulianPasquale marked this conversation as resolved.

subject do
create(:user)
end
Comment thread
JulianPasquale marked this conversation as resolved.

context 'when given value is different from password' do
it 'has to return false' do
expect(subject.valid_password?(password)).to be false
end
end

context 'when given value is equal to password' do
it 'has to return true' do
expect(subject.valid_password?(subject.password)).to be true
end
end
end
end
Comment thread
JulianPasquale marked this conversation as resolved.
86 changes: 59 additions & 27 deletions spec/services/api_login_manager_spec.rb
Original file line number Diff line number Diff line change
@@ -1,87 +1,119 @@
require 'rails_helper'

# Los skips sirven para prevenir la ejecución del it, así que es necesario
# borrarlos (en su lugar implementen los tests, no sean vagos).

RSpec.describe ApiLoginManager do
# Idealmente la contraseña del usuario estaría encriptada en la base
# de datos, por lo que no vamos a poder recuperarla del usuario para
# utilizarla. Es por eso que conviene usarla desde una variable con
# let!(:password) { SecureRandom.hex }. Al crear el usuario,
# en let!(:user) { ... }, usar esta variable.
let!(:password) { SecureRandom.hex }

let!(:user) { } # -- crear usuario con FactoryBot -- #
let!(:user) { create(:user, password: password) }

describe '#call' do
context 'when user provided data is valid' do
before do
# Realizar un stub del ExternalValidator para que se ejecuta realmente
allow(ExternalValidator).to receive(:call).and_return(true)
end

subject do
described_class.new(email: user.email, password: password).call
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 }
# skip 'Una vez que definan a user, este test va a fallar. ¿Por qué?'

# Esto es porque el registro no se actualizo con los datos modificados
# luego de la llamada a ApiLoginManager, por lo que es necesario hacer
# un reload

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)
# Por qué esto no anda pero lo de arriba si?
# expect(user.reload.auth_token).to eq(subject)
end
end

context 'when no email is provided' do
subject { } # implementar
subject do
described_class.new(password: password)
end

let!(:subject_response) { subject.call }

it 'returns false' do
skip 'Implementar'
expect(subject_response).to be false
end

it 'returns EMPTY_EMAIL error with a reader' do
skip 'Implementar'
expect(subject.error).to eq(ApiLoginManager::EMPTY_EMAIL)
end
end

context 'when no password is provided' do
subject { } # implementar
subject do
described_class.new(email: user.email)
end

let!(:subject_response) { subject.call }

it 'returns false' do
skip 'Implementar'
expect(subject_response).to be false
end

it 'returns EMPTY_PASSWORD error with a reader' do
skip 'Implementar'
expect(subject.error).to eq(ApiLoginManager::EMPTY_PASSWORD)
end
end

context 'when the email is incorrect' do
subject { } # implementar
subject do
described_class.new(email: Faker::Internet.email, password: password)
end

let!(:subject_response) { subject.call }

it 'returns false' do
skip 'Implementar'
expect(subject_response).to be false
end

it 'returns USER_NOT_FOUND error with a reader' do
skip 'Implementar'
expect(subject.error).to eq(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

let!(:subject_response) { subject.call }

it 'returns false' do
skip 'Implementar'
expect(subject_response).to be false
end

it 'returns WRONG_PASSWORD error with a reader' do
skip 'Implementar'
expect(subject.error).to eq(ApiLoginManager::WRONG_PASSWORD)
end
end

# Definir un nuevo context para cuando la conexión
# con ExternalValidator falla. Acá los quiero ver...
context 'when ExternalValidator conection fails' do
before do
allow(ExternalValidator).to receive(:call).and_return(false)
end

subject do
described_class.new(email: user.email, password: password)
end

let!(:subject_response) { subject.call }

it 'returns false' do
expect(subject_response).to be false
end

it 'returns EXTERNAL_VALIDATOR error with a reader' do
expect(subject.error).to eq(ApiLoginManager::EXTERNAL_VALIDATOR)
end
end
end
end