Minitest - test class in Rails 4 - ruby-on-rails-4

I am trying to use Minitest in a fresh Rails 4 install. My understanding is that if I have a class that doesn't inherit from ActiveRecord then I should be able to use Minitest itself, without Rails integration:
#test/models/blog.rb
require "minitest/autorun"
class Blog < Minitest::Unit::TestCase
def setup
#b = Blog.new
end
def test_entries
assert_empty "message", #b.entries
end
#app/models/blog.rb
class Blog
attr_reader :entries
def initialize
#entries = []
end
I run the test with ruby test/models/blog.rb.
My problem comes with the setup method. If I don't include an entry for my blog, the tests fails with the message that there are the wrong number of arguments in setup. If I include an entry in my setup message #b = Blog.new entries: "Twilight", my test fails in the test_entries method because entries is an undefined method.

You have a couple problems. First, you are not requiring "test_helper", which means that rails isn't getting loaded when you run this test, which means that the mechanism rails uses to resolve missing constants isn't loaded. You will either need to require the helper or require the blog file directly. Second, you are overwriting the constant you want to test with the test, which is why you are getting confusing messages. Name the test class BlogTest instead to avoid this.
This is what I think you are trying to do:
require "minitest/autorun"
require "models/blog" # Assuming "app" is in your load path when running the test
#require "test_helper" # Or require this instead if you need to use DB
class BlogTest < Minitest::Unit::TestCase
def setup
#b = Blog.new
end
def test_entries
assert_empty #b.entries, "Blog entries should be empty"
end
end

Related

In Rails4, using Trailblazer, how do I access the current_user

We are building a Rails4 app using Trailblazer. I have never worked with Trailblazer before and I am confused about how to do things.
We are building an auction site. I was previously using a traditional controller, and this route endpoint was working fine:
def bill
#profile = Profile.find_by user_id: current_user_id
#current_order = Order.order(created_at: :desc).find_by(user_id: current_user_id)
#batch = #current_order.batch
if #batch.nil?
puts "There was no batch linked to the current order of #{#current_order.id}"
flash[:error] = "We are sorry, but we could not determine which batch your order belongs to."
else
#price_shown_to_customer = #batch.price + ENV["FUELBID_FEE_PER_GALLON"].to_f
#amount = #current_order.quantity * #price_shown_to_customer
end
But now I'm suppose to create this as a Trailblazer api, using a Representer class.
So in routes.rb I added something for "charges":
namespace :api do
get '/price' => 'info#info'
post '/order' => 'orders#create'
get '/charges' => 'charges#bill'
end
I created this Api but copying-and-pasting another:
module Api
class ChargesController < ApiApplicationController
respond_to :json
def bill
respond_with OpenStruct.new.extend(ChargesRepresenter)
end
end
end
I tested the above with a simple Representer and it all worked fine, so everything is good up to this point. If I return simple data from the Representer, then I can see it fine here:
http://localhost:3000/api/charges.json
But I need to get the current_user. How is this done? Right now, this does not work:
module ChargesRepresenter
include Roar::JSON
collection :price_shown_to_customer
def price_shown_to_customer
current_order = Order.order(created_at: :desc).find_by(user_id: current_user_id)
puts "current_order"
puts current_order.id
batch = current_order.batch
batch.price + ENV["FUELBID_FEE_PER_GALLON"].to_f
end
end
current_user_id exists in my traditional controllers because we set up Devise and so my traditional controllers inherit it:
class ChargesController < SecuredController
But is there any way to get it in a Trailblazer Representer?
Hope this answer is not too late.
If you can switch to Decorator pattern instead of a Module.
Representer really doesn't need to know and doesn't care if it is called from controller or console or test. All it needs is a hash to build your json object from. So you can just pass another attribute called current_user_id to your Representer and then use it inside r presenter like you do.
FYI:
If you need a more immediate response you can also copy your question to https://gitter.im/trailblazer/chat . There are usually several people hanging out there. But it's also good to post a question here for posterity.

Why is Digest::SHA1 preventing proper annotation of a model?

I am using annotate in my app and all models are successfully annotated except for user.rb, which shows the following error when I annotate:
Unable to annotate user.rb: wrong number of arguments (0 for 1)
Outside of annotating, everything else works fine. User creation, updating, deletion, login, sign out, it all works properly. I have determined that the problem is with the Digest::SHA1, which I use to create session tokens, as demonstrated below in the snippet from user.rb.
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.hash(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
remember_token = User.hash(User.new_remember_token)
end
If I remove the second (def User.hash(token)) and instead do the following:
def User.new_remember_token
SecureRandom.urlsafe_base64
end
private
def create_remember_token
remember_token = Digest::SHA1.hexdigest(User.new_remember_token.to_s)
end
then annotate is happy and successfully annotates user.rb. However, this isn't really the ruby way as my session helper utilizes that User.hash(token) call several times. What am I not understanding about Digest::SHA1.hexdigest or the way that I am utilizing it?
Looks like you're working through The Rails Tutorial.
The likely reason you're seeing issues with your User.hash method is nothing to do with Digest::SHA1, but is because the method itself is inadvertently overriding Ruby's Object#hash method, which is giving you some cryptic errors. Link to Github issue about it.
So, like this commit to the Sample App repository, rename all your instances of User.hash to User.digest and hopefully that should fix your errors.

Rails: testing custom classes with RSpec

Yea, I know that this question is silly, newbee and simple, but I still can't figure it out.
I've created a class (in app/minions/ directory) to parse auth hashes from 3rd-party services (like google, twitter, etc.). It looks like this.
class AuthHash
def initialize(hash)
#hash = hash
#provider = hash[:provider]
#uid = hash[:uid]
create_user_hash
end
def create_user_hash
#user_hash = send("parse_hash_from_" << #hash[:provider], #hash)
end
def credentials
{provider: #provider, uid: #uid}
end
def user_hash
#user_hash
end
private
# parse_hash_from_* methods here
end
I've added that directory to the autoload path, so I can use it in my controllers. Now I want to write some tests for it.
I'm using RSpec with FactoryGirl for testing. So I started by adding a factory to spec/factories/ called auth_hashes.rb but I can't define a hash as a field in a factory.
So I moved the declaration to the spec/minions/auth_hash_spec.rb.
require 'spec_helper'
describe AuthHash do
before_each do
auth_hash = AuthHash.new({:provider=>"google_oauth2",:uid=>"123456789",:info=>{:name=>"JohnDoe",:email=>"john#company_name.com",:first_name=>"John",:last_name=>"Doe",:image=>"https://lh3.googleusercontent.com/url/photo.jpg"},:credentials=>{:token=>"token",:refresh_token=>"another_token",:expires_at=>1354920555,:expires=>true},:extra=>{:raw_info=>{:id=>"123456789",:email=>"user#domain.example.com",:verified_email=>true,:name=>"JohnDoe",:given_name=>"John",:family_name=>"Doe",:link=>"https://plus.google.com/123456789",:picture=>"https://lh3.googleusercontent.com/url/photo.jpg",:gender=>"male",:birthday=>"0000-06-25",:locale=>"en",:hd=>"company_name.com"}}})
end
end
But still it does not seem to work.
I know this should be alot simpler then I'm trying to do, but I can't figure it out.
Add something like this to that new spec (spec/minions/auth_hash_spec.rb) file at the top:
require Rails.root.to_s + '/app/minions/myhash.rb'
And then write your tests.

setting up controller for test

i'm trying to write a functional test for my controller in rubymotion using bacon.
in my controller i have some code that populates some data:
def viewWillAppear(animated)
song_text.text = chant.song_text
...
end
i am setting the chant variable when i push that controller to the navigation-controller.
this works fine in the app, but when i try to do that in a before-block of the spec it does not work, because viewWillAppear gets called before the block and it fails with a NoMethodError: undefined method 'song_text' for nil:NilClass.
is there some way to handle this situation? is there some other way to populate the data or use a different method than viewWillAppear?
I've experience a similar issue that was solved by calling the super method in the viewWillAppear method
The RubyMotion support answered my support ticket indicating, that this is the expected behavior of controllers in bacon.
I worked around the whole thing by stubbing my class under test in the bacon spec like so:
# spec/chant_controller_spec.rb
class ChantControllerStub < ChantController
def chant
#chant ||= create_chant
end
end
describe "ChantController" do
tests ChantControllerStub
it "displays a chant" do
view('verse').should.not == nil
end
end

Adding validates_uniqueness_of to a model fails functional tests

Trying to make a simple application in rails 3.
If I create a team model with rails g scaffold team name:string && rake db:migrate, then run rake, I get success from the prebuilt tests.
If I simply add validates_uniqueness_of :name to the team model. The functional tests fail with
1) Failure:
test_should_create_team(TeamsControllerTest) [/test/functional/teams_controller_test.rb:20]:
"Team.count" didn't change by 1.
<3> expected but was
<2>.
I modified tests/fixtures/teams.yml to look like this:
one:
name: MyString
two:
name: MyString2
The test still fails.
It can't get much more basic than this; what have I missed?
Fixtures basically represent model instances that are in the database.
If you look at the top of test/functional/teams_controller_test.rb you'll see
setup do
#team = teams(:one)
end
and then in your failing functional test you'll have
post :create, :team => #team.attributes
This is what's happening: you're trying to create a new team with the same attributes as "the team fixture named :one". Since both would have the same name (since they have the exact same attributes), the uniqueness validation is failing.
Try replacing your setup block with this
setup do
#team = teams(:one)
#team.name = 'unique name'
end
Now you'll be creating a new team with the name 'unique name' (which isn't in the database according to the fixtures), and your test will pass.