Skip to content

Commit

Permalink
Refactor test suites
Browse files Browse the repository at this point in the history
  • Loading branch information
binos30 committed Dec 26, 2024
1 parent cd0a6da commit dfe20a8
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 66 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ To test Stripe payments, use the following test card details:

1. Go to the [Stripe Dashboard](https://dashboard.stripe.com) and create a new webhook for your production environment.
2. Set the endpoint URL to your production route (e.g., `https://yourdomain.com/stripe_webhooks`).
3. Select the events you want to listen for (e.g., `checkout.session.completed`, `customer.created`).
3. Select the events you want to listen for (e.g., `checkout.session.completed`, `customer.created`, `customer.deleted`).

## GitHub Actions, Linting and Security Auditing

Expand Down Expand Up @@ -135,6 +135,16 @@ See all options for running specs
bin/rspec --help
```

## Code Coverage

[Coverage]: https://docs.ruby-lang.org/en/3.3/Coverage.html "API doc for Ruby's Coverage library"
[SimpleCov]: https://github.com/simplecov-ruby/simplecov "A code coverage analysis tool for Ruby"

[SimpleCov][SimpleCov] is a code coverage analysis tool for Ruby. It uses [Ruby's built-in Coverage][Coverage] library to
gather code coverage data, but makes processing its results much easier by providing a clean API to filter, group, merge, format,
and display those results, giving you a complete code coverage suite that can be set up with just a couple lines of code.
SimpleCov/Coverage track covered ruby code, gathering coverage for common templating solutions like erb, slim and haml is not supported.

After running your tests, open `coverage/index.html` in the browser of your choice. For example, in a Mac Terminal,
run the following command from your application's root directory:

Expand Down
4 changes: 2 additions & 2 deletions app/controllers/webhooks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def stripe # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/Cyclom
end
when "customer.created"
customer = event.data.object
user = User.find_by!(email: customer.email)
user.update!(stripe_customer_id: customer.id)
user = User.find_by(email: customer.email)
user&.update!(stripe_customer_id: customer.id)
when "customer.deleted"
customer = event.data.object
user = User.find_by(stripe_customer_id: customer.id)
Expand Down
54 changes: 54 additions & 0 deletions spec/models/order_item_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe OrderItem, type: :model do
describe "db_columns" do
it { should have_db_column(:order_id).of_type(:integer).with_options(null: false) }
it { should have_db_column(:product_id).of_type(:integer).with_options(null: false) }
it { should have_db_column(:stock_id).of_type(:integer).with_options(null: false) }
it { should have_db_column(:order_code).of_type(:string).with_options(null: false) }
it { should have_db_column(:product_name).of_type(:string).with_options(null: false) }
it do
should have_db_column(:product_price).of_type(:decimal).with_options(
null: false,
default: 0.0,
precision: 12,
scale: 2
)
end
it { should have_db_column(:size).of_type(:string).with_options(null: false) }
it { should have_db_column(:quantity).of_type(:integer).with_options(null: false) }
it { should have_db_column(:subtotal).of_type(:decimal).with_options(null: false, precision: 12, scale: 2) }
end

describe "db_indexes" do
it { should have_db_index(:order_code) }
it { should have_db_index(:order_id) }
it { should have_db_index(:product_id) }
it { should have_db_index(:stock_id) }
end

describe "associations" do
describe "belongs_to" do
it { should belong_to(:order).inverse_of(:order_items) }
it { should belong_to(:product).inverse_of(:order_items) }
it { should belong_to(:stock).inverse_of(:order_items) }
end
end

describe "validations" do
describe "presence" do
it { should validate_presence_of(:order_code) }
it { should validate_presence_of(:product_name) }
it { should validate_presence_of(:size) }
it { should validate_presence_of(:quantity) }
it { should validate_presence_of(:product_price) }
end

describe "numericality" do
it { should validate_numericality_of(:quantity).is_greater_than(0) }
it { should validate_numericality_of(:product_price).is_greater_than_or_equal_to(0) }
end
end
end
18 changes: 10 additions & 8 deletions spec/models/role_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@
describe "format" do
subject { build :role }

it "name accepts a valid value" do
subject.name = "role"
expect(subject).to be_valid
end

it "name does not accept an invalid format" do
subject.name = "role-1"
expect(subject).to be_invalid
describe "name" do
it "accepts a valid value" do
subject.name = "role"
expect(subject).to be_valid
end

it "does not accept an invalid format" do
subject.name = "role-1"
expect(subject).to be_invalid
end
end
end
end
Expand Down
18 changes: 10 additions & 8 deletions spec/models/subscriber_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@
describe "format" do
subject { build :subscriber }

it "email accepts a valid value" do
subject.email = "subscriber@email.com"
expect(subject).to be_valid
end

it "email does not accept an invalid format" do
subject.email = "subscriber@"
expect(subject).to be_invalid
describe "email" do
it "accepts a valid value" do
subject.email = "subscriber@email.com"
expect(subject).to be_valid
end

it "does not accept an invalid format" do
subject.email = "subscriber@"
expect(subject).to be_invalid
end
end
end
end
Expand Down
95 changes: 48 additions & 47 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,47 @@

RSpec.describe User, type: :model do
describe "db_columns" do
it { is_expected.to have_db_column(:email).of_type(:string).with_options(null: false, default: "") }
it do
is_expected.to have_db_column(:encrypted_password).of_type(:string).with_options(null: false, default: "")
end
it { is_expected.to have_db_column(:reset_password_token).of_type(:string) }
it { is_expected.to have_db_column(:reset_password_sent_at).of_type(:datetime) }
it { is_expected.to have_db_column(:remember_created_at).of_type(:datetime) }
it { is_expected.to have_db_column(:sign_in_count).of_type(:integer).with_options(null: false, default: 0) }
it { is_expected.to have_db_column(:current_sign_in_at).of_type(:datetime) }
it { is_expected.to have_db_column(:last_sign_in_at).of_type(:datetime) }
it { is_expected.to have_db_column(:current_sign_in_ip).of_type(:string) }
it { is_expected.to have_db_column(:last_sign_in_ip).of_type(:string) }
it { is_expected.to have_db_column(:first_name).of_type(:string).with_options(null: false) }
it { is_expected.to have_db_column(:last_name).of_type(:string).with_options(null: false) }
it { is_expected.to have_db_column(:phone_number).of_type(:string) }
it { is_expected.to have_db_column(:active).of_type(:boolean).with_options(null: false, default: true) }
it { is_expected.to have_db_column(:role_id).of_type(:integer).with_options(null: false) }
it { is_expected.to have_db_column(:gender).of_type(:string).with_options(null: false) }
it { is_expected.to have_db_column(:deleted_at).of_type(:datetime) }
it { is_expected.to have_db_column(:stripe_customer_id).of_type(:string) }
it { should have_db_column(:email).of_type(:string).with_options(null: false, default: "") }
it { should have_db_column(:encrypted_password).of_type(:string).with_options(null: false, default: "") }
it { should have_db_column(:reset_password_token).of_type(:string) }
it { should have_db_column(:reset_password_sent_at).of_type(:datetime) }
it { should have_db_column(:remember_created_at).of_type(:datetime) }
it { should have_db_column(:sign_in_count).of_type(:integer).with_options(null: false, default: 0) }
it { should have_db_column(:current_sign_in_at).of_type(:datetime) }
it { should have_db_column(:last_sign_in_at).of_type(:datetime) }
it { should have_db_column(:current_sign_in_ip).of_type(:string) }
it { should have_db_column(:last_sign_in_ip).of_type(:string) }
it { should have_db_column(:first_name).of_type(:string).with_options(null: false) }
it { should have_db_column(:last_name).of_type(:string).with_options(null: false) }
it { should have_db_column(:phone_number).of_type(:string) }
it { should have_db_column(:active).of_type(:boolean).with_options(null: false, default: true) }
it { should have_db_column(:role_id).of_type(:integer).with_options(null: false) }
it { should have_db_column(:gender).of_type(:string).with_options(null: false) }
it { should have_db_column(:deleted_at).of_type(:datetime) }
it { should have_db_column(:stripe_customer_id).of_type(:string) }
end

describe "db_indexes" do
it { is_expected.to have_db_index(:active) }
it { is_expected.to have_db_index(:email).unique }
it { is_expected.to have_db_index(:first_name) }
it { is_expected.to have_db_index(:last_name) }
it { is_expected.to have_db_index(:gender) }
it { is_expected.to have_db_index(:role_id) }
it { is_expected.to have_db_index(:reset_password_token).unique }
it { is_expected.to have_db_index(:stripe_customer_id).unique }
it { should have_db_index(:active) }
it { should have_db_index(:email).unique }
it { should have_db_index(:first_name) }
it { should have_db_index(:last_name) }
it { should have_db_index(:gender) }
it { should have_db_index(:role_id) }
it { should have_db_index(:reset_password_token).unique }
it { should have_db_index(:stripe_customer_id).unique }
end

describe "associations" do
describe "belongs_to" do
# Use `without_validating_presence` with `belong_to` to prevent the
# matcher from checking whether the association disallows nil (Rails 5+ only).
# This can be helpful if you have a custom hook that always sets
# the association to a meaningful value:
it { is_expected.to belong_to(:role).inverse_of(:users).without_validating_presence }
# This can be helpful if you have a custom hook that always sets the association to a meaningful value:
it { should belong_to(:role).inverse_of(:users).without_validating_presence }
end

describe "has_many" do
it { is_expected.to have_many(:orders).inverse_of(:user).dependent(:restrict_with_exception) }
it { should have_many(:orders).inverse_of(:user).dependent(:restrict_with_exception) }
end
end

Expand All @@ -72,7 +69,7 @@
end

describe "inclusion" do
it { is_expected.to validate_inclusion_of(:gender).in_array(User.genders.keys) }
it { should validate_inclusion_of(:gender).in_array(User.genders.keys) }
end

describe "length" do
Expand All @@ -98,24 +95,28 @@
describe "format" do
subject { build :user }

it "first_name accepts a valid value" do
subject.first_name = "John"
expect(subject).to be_valid
end
describe "first_name" do
it "accepts a valid value" do
subject.first_name = "John"
expect(subject).to be_valid
end

it "first_name does not accept an invalid format" do
subject.first_name = "John-1"
expect(subject).to be_invalid
it "does not accept an invalid format" do
subject.first_name = "John-1"
expect(subject).to be_invalid
end
end

it "last_name accepts a valid value" do
subject.last_name = "Doe"
expect(subject).to be_valid
end
describe "last_name" do
it "accepts a valid value" do
subject.last_name = "Doe"
expect(subject).to be_valid
end

it "last_name does not accept an invalid format" do
subject.last_name = "Doe-1"
expect(subject).to be_invalid
it "does not accept an invalid format" do
subject.last_name = "Doe-1"
expect(subject).to be_invalid
end
end
end

Expand Down

0 comments on commit dfe20a8

Please sign in to comment.