Skip to content

Commit

Permalink
Merge pull request #19 from fmanimashaun/features/models-unit-testing
Browse files Browse the repository at this point in the history
[3pt] Write Unit Tests for Models
  • Loading branch information
fmanimashaun authored Feb 16, 2024
2 parents ee07dd2 + dd44b54 commit f64b6d5
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
gem install --no-document rubocop -v '>= 1.0, < 2.0' # https://docs.rubocop.org/en/stable/installation/
[ -f .rubocop.yml ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ror/.rubocop.yml
- name: Rubocop Report
run: rubocop --color
run: rubocop --color -A
nodechecker:
name: node_modules checker
runs-on: ubuntu-22.04
Expand Down
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ group :development do
# gem "spring"
end

group :test do
gem 'shoulda-matchers'
end

gem 'devise'
gem 'devise-jwt'
gem 'jsonapi-serializer'
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ GEM
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
shoulda-matchers (6.1.0)
activesupport (>= 5.2.0)
stringio (3.1.0)
thor (1.3.0)
timeout (0.4.1)
Expand Down Expand Up @@ -320,6 +322,7 @@ DEPENDENCIES
rswag-specs
rswag-ui
rubocop
shoulda-matchers
tzinfo-data

RUBY VERSION
Expand Down
2 changes: 2 additions & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
default: &default
adapter: postgresql
encoding: unicode
username: postgres
password: "BrunoyKino2019@"
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
Expand Down
3 changes: 2 additions & 1 deletion spec/factories/car_details.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
FactoryBot.define do
factory :car_detail do
car { nil }
engine_type { nil }
horsepower { 1 }
torque { 1 }
fuel_economy { 'MyString' }
Expand All @@ -11,5 +10,7 @@
safety_rating { 'MyString' }
tech_features { 'MyString' }
special_features { 'MyString' }

association :engine_type
end
end
2 changes: 1 addition & 1 deletion spec/factories/cars.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FactoryBot.define do
factory :car do
name { 'MyString' }
description { 'MyText' }
description { 'MyText with length of more than 10 characters' }
end
end
5 changes: 3 additions & 2 deletions spec/factories/reservations.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
FactoryBot.define do
factory :reservation do
date { '2024-02-15' }
city { nil }
date { Date.today }
car { nil }
user { nil }

association :city
end
end
13 changes: 13 additions & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FactoryBot.define do
factory :user do
sequence(:username) { |n| "username#{n}" }
name { 'John Doe' }
email { 'john@example.com' }
password { 'Password123' }
role { :user }

trait :admin do
role { :admin }
end
end
end
27 changes: 26 additions & 1 deletion spec/models/car_detail_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
require 'rails_helper'

RSpec.describe CarDetail, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:car) { FactoryBot.create(:car) }
let(:engine_type) { FactoryBot.create(:engine_type) }

let(:car_detail) { FactoryBot.create(:car_detail, car:, engine_type:) }

it 'Creates a reservation with valid attributes' do
expect(car_detail).to be_valid
end

it 'is invalid withinvalid attributes' do
car_detail = FactoryBot.build(
:car_detail,
horsepower: nil,
car: nil,
torque: nil,
fuel_economy: nil,
seating_capacity: nil,
cargo_space: nil,
infotainment_system: nil,
safety_rating: nil,
tech_features: nil,
special_features: nil
)

expect(car_detail).to_not be_valid
end
end
49 changes: 48 additions & 1 deletion spec/models/car_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
require 'rails_helper'
require 'shoulda/matchers'

RSpec.describe Car, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:car) { FactoryBot.create(:car) }

it 'is valid with a name' do
expect(car).to be_valid
end

it 'is invalid without a name' do
car = FactoryBot.build(:car, name: nil)

expect(car).to_not be_valid
end

it 'is invalid when the name is too short' do
car = FactoryBot.build(:car, name: 'V')

expect(car).to_not be_valid
end

it 'is invalid when the name is too long' do
car = FactoryBot.build(:car, name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet
massa vel nulla eleifend semper sed vel est. Phasellus nulla metus, molestie vel condimentum sit amet, commodo sed
libero. Sed massa tellus, auctor sed varius vitae, egestas nec felis. Curabitur sit amet laoreet turpis, non
sagittis neque. Proin venenatis ipsum arcu, non aliquam risus blandit eget. Integer sed facilisis nibh.
Pellentesque eleifend dignissim leo, condimentum interdum metus molestie nec. Phasellus ut enim faucibus,
facilisis orci in, porttitor ex. Nunc mollis felis odio, sed sollicitudin metus iaculis eget. Nunc cursus, leo
vitae ultricies commodo, nunc elit porta ligula, in fermentum magna purus et arcu. Vivamus augue eros, elementum
egestas efficitur vel, feugiat quis mi. Ut sit amet venenatis ligula, id dignissim odio. Duis at magna ultricies,
vulputate sem non, ullamcorper arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit.")

expect(car).to_not be_valid
end

it 'can have many reservations' do
engine_type = FactoryBot.create(:engine_type)
FactoryBot.create(:car_detail, engine_type:, car:)
user = FactoryBot.create(:user)
city = FactoryBot.create(:city)

reservation1 = FactoryBot.create(:reservation, car:, city:, user:)
reservation2 = FactoryBot.create(:reservation, car:, city:, user:)

expect(car.reservations).to include(reservation1, reservation2)
end

it 'accepts nested attributes for car_detail' do
should accept_nested_attributes_for(:car_detail)
end
end
46 changes: 45 additions & 1 deletion spec/models/city_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
require 'rails_helper'

RSpec.describe City, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:city) { FactoryBot.create(:city) }

it 'Creates a city with valid attributes' do
expect(city).to be_valid
end

describe 'fails to create a city with invalid attributes' do
it 'Name attribute is not present' do
city = FactoryBot.build(:city, name: nil)

expect(city).to_not be_valid
end

it 'name attribute is too long' do
city = FactoryBot.build(:city, name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed sem lectus.
Ut non fermentum velit. Nunc facilisis diam id ante auctor rutrum. Proin mauris ipsum, scelerisque et convallis
ac, molestie quis turpis. Vivamus rhoncus ex non arcu mattis, non sollicitudin est pellentesque. Curabitur neque
risus, dignissim placerat enim eget, facilisis efficitur nisl. In dictum, diam ullamcorper hendrerit malesuada,
augue magna cursus sapien, dignissim interdum elit ante non dui. Suspendisse tempus orci vel orci imperdiet,
eget rutrum lacus cursus. In dictum facilisis mauris, id euismod neque tincidunt aliquet. Aenean consectetur
lacus eget efficitur sagittis. Phasellus a sem eu leo viverra pharetra vitae in metus. Fusce suscipit scelerisque
faucibus. Proin et ex porta, suscipit erat et, semper enim. In lobortis egestas nulla dictum aliquet. Sed eget
consectetur nibh. Maecenas egestas et quam scelerisque consequat.")

expect(city).to_not be_valid
end

it 'name attribute is too short' do
city = FactoryBot.build(:city, name: '')

expect(city).to_not be_valid
end
end

it 'It can have many reservation records' do
engine_type = FactoryBot.create(:engine_type)
car = FactoryBot.create(:car)
FactoryBot.create(:car_detail, engine_type:, car:)
user = FactoryBot.create(:user)

reservation1 = FactoryBot.create(:reservation, car:, city:, user:)
reservation2 = FactoryBot.create(:reservation, car:, city:, user:)

expect(city.reservations).to include(reservation1, reservation2)
end
end
23 changes: 22 additions & 1 deletion spec/models/engine_type_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
require 'rails_helper'

RSpec.describe EngineType, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:engine_type) { FactoryBot.create(:engine_type) }

it 'is valid with a name' do
expect(engine_type.name).to eq('MyString')
expect(engine_type).to be_valid
end

it 'is invalid without a name' do
engine_type = FactoryBot.build(:engine_type, name: nil)

expect(engine_type.name).to eq(nil)
expect(engine_type).to_not be_valid
end

it 'has can have many car details' do
engine_type = FactoryBot.create(:engine_type)
car = FactoryBot.create(:car)
car_detail1 = FactoryBot.create(:car_detail, car:, engine_type:)
car_detail2 = FactoryBot.create(:car_detail, car:, engine_type:)

expect(engine_type.car_details).to include(car_detail1, car_detail2)
end
end
35 changes: 34 additions & 1 deletion spec/models/reservation_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
require 'rails_helper'

RSpec.describe Reservation, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:city) { FactoryBot.create(:city) }
let(:car) { FactoryBot.create(:car) }
let(:user) { FactoryBot.create(:user) }
let(:reservation) { FactoryBot.create(:reservation, car:, city:, user:) }

it 'Creates a reservation with valid attributes' do
expect(reservation).to be_valid
end

describe 'with invalid attributes' do
it "Doesn't create a reservation with invalid car attribute" do
reservation = FactoryBot.build(:reservation, car: nil)

expect(reservation).to_not be_valid
end

it "Doesn't create a reservation with invalid city attribute" do
reservation = FactoryBot.build(:reservation, city: nil)

expect(reservation).to_not be_valid
end

it "Doesn't create a reservation with invalid user attribute" do
reservation = FactoryBot.build(:reservation, user: nil)

expect(reservation).to_not be_valid
end
end

describe 'associations' do
it { should belong_to(:city) }
it { should belong_to(:car) }
it { should belong_to(:user) }
end
end
43 changes: 43 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require 'rails_helper'

RSpec.describe User, type: :model do
describe 'validations' do
it { should validate_presence_of(:username) }
it { should validate_presence_of(:name) }
it { should validate_presence_of(:email) }
it { should validate_length_of(:password).is_at_least(8) }
it { should allow_value('username').for(:username) }
it { should_not allow_value('user name').for(:username) }
it { should_not allow_value('user@name').for(:username) }
it { should_not allow_value('user name!').for(:username) }
end

describe 'associations' do
it { should have_many(:reservations).dependent(:destroy) }
end

describe 'enums' do
it { should define_enum_for(:role).with_values(user: 0, admin: 1) }
end

describe 'after_initialize' do
it 'sets the default role to user' do
user = User.new
expect(user.role).to eq('user')
end
end

describe 'methods' do
describe '#admin?' do
it 'returns true if the user has admin role' do
admin_user = FactoryBot.create(:user, :admin)
expect(admin_user.admin?).to be_truthy
end

it 'returns false if the user does not have admin role' do
user = FactoryBot.create(:user)
expect(user.admin?).to be_falsey
end
end
end
end
5 changes: 5 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
abort e.to_s.strip
end
RSpec.configure do |config|
# configurations for Shoulda Matchers
config.include FactoryBot::Syntax::Methods
config.include Shoulda::Matchers::ActiveModel, type: :model
config.include Shoulda::Matchers::ActiveRecord, type: :model

# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_paths = [
Rails.root.join('spec/fixtures')
Expand Down

0 comments on commit f64b6d5

Please sign in to comment.