Finished Implementation
Let’s finalize the test implementation for our Rails application.
We'll cover the following...
We know it’ll make this section even longer, but let’s quickly go through the remainder of the implementation. Here are the remaining tests:
Press + to interact
# test/services/widget_creator_test.rbassert_equal "finance@example.com", mail_message["to"].to…assert_match /Stembolt/, mail_message.text_part.to_send→ test "name, price, and manufacturer are required" do→ result = @widget_creator.create_widget(Widget.new)→→ refute result.created?→→ widget = result.widget→ assert widget.invalid?→→ assert widget.errors[:name].any? { |message|→ message =~ /canott be blank/i→ }, widget.errors.full_messages_for(:name)→→ assert widget.errors[:price_cents].any? { |message|→ message =~ /is not a number/i→ }, widget.errors.full_messages_for(:price_cents)→→ assert widget.errors[:manufacturer].any? { |message|→ message =~ /must exist/i→ }, widget.errors.full_messages_for(:manufacturer)→→ end→→ test "price cannot be 0" do→ result = @widget_creator.create_widget(Widget.new(→ name: "Stembolt",→ price_cents: 0,→ manufacturer_id: @manufacturer.id→ ))→→ refute result.created?→→ assert result.widget.errors[:price_cents].any? { |message|→ message =~ /greater than 0/i→ }, result.widget.errors.full_messages_for(:price_cents)→→ end→→ test "price cannot be more than 10,000" do→ result = @widget_creator.create_widget(Widget.new(→ name: "Stembolt",→ price_cents: 10_000_01,→ manufacturer_id: @manufacturer.id→ ))→→ refute result.created?→→ assert result.widget.errors[:price_cents].any? { |message|→ message =~ /less than or equal to 1000000/i→ }, result.widget.errors.full_messages_for(:price_cents)→→ end→→ test "legacy manufacturers cannot have a price under $100" do→ legacy_manufacturer = FactoryBot.create(:manufacturer,→ created_at: DateTime.new(2010,1,1) - 1.day)→→ result = @widget_creator.create_widget(Widget.new(→ name: "Stembolt",→ price_cents: 99_00,→ manufacturer_id: legacy_manufacturer.id→ ))→→ refute result.created?→→ assert result.widget.errors[:price_cents].any? { |message|→ message =~ /< \$100.*legacy/i→ }, result.widget.errors.full_messages_for(:price_cents)→ end→ test "email admin staff for widgets on new manufacturers " do→ new_manufacturer = FactoryBot.create(:manufacturer,→ name: "Cyberdyne Systems",→ created_at: 59.days.ago)→→ result = @widget_creator.create_widget(Widget.new(→ name: "Stembolt",→ price_cents: 99_00,→ manufacturer_id: new_manufacturer.id→ ))→→ assert result.created?→→ assert_equal 1, ActionMailer::Base.deliveries.size→ mail_message = ActionMailer::Base.deliveries.first→ assert_equal "admin@example.com", mail_message["to"].to_s→ assert_match /Stembolt/, mail_message.text_part.to_s→ assert_match /Cyberdyne Systems/, mail_message.text_part.to_s→ endend
The first test (that tests for omitting all of the values) fails, but not in the right way. Our WidgetCreator
has a bug, in that it assumes price_cents
has a value. We can fix that by early-exiting when we see the widget is invalid:
Press + to interact
# app/services/widget_creator.rbwidget.widget_status =WidgetStatus.find_by!(name: "Fresh")widget.save→ if widget.invalid?→ return Result.new(created: false, widget: widget)→ endif widget.price_cents > 7_500_00FinanceMailer.high_priced_widget(widget).deliver_nowend
Next, we’ll trigger the mailer to the admin team. We’ll need that mailer:
Press + to interact
# app/mailers/admin_mailer.rbclass AdminMailer < ApplicationMailerdef new_widget_from_new_manufacturer(widget)@widget = widgetmail to: "admin@example.com"endend
Like FinanceMailer
, the views can be minimal for now:
<%# app/views/admin_mailer/new_widget_from_new_manufacturer.html.erb
...