How do I test this Sinatra Method? - ruby

Trivial Sinatra application:
require 'rubygems'
require 'sinatra/base'
require 'haml'
class InfoController < Sinatra::Base
get "/" do
haml :index
end
end
And my test:
describe InfoController do
include Rack::Test::Methods
def app
InfoController
end
it "should return the index page when visiting the root of the site" do
get '/'
last_response.should be_ok
end
end
But I do not want to test whether or not the haml method worked, I just want to test that the index view was rendered.
How would you test that? Redefine the haml method? Mock the haml method somehow?

What about testing the actual markup that was rendered?
last_response.body.should match(/your text/)

Related

Sinatra App - Separating Concerns

Probably something really basic, but I want to be able to separate my Sinatra routes from controllers. I have this code in my routes.rb:
require 'sinatra/base'
class Server < Sinatra::Base
get '/' do
Action.index
end
end
This is my controller/server.rb
class Action
def sef.index
#user = User.new("Abiodun Shuaib")
haml: index
end
end
It gives the error undefined method 'haml' in Action:Class.
How can I fix this?
You are trying to access method haml in class Action. It simply doesn't contain it.
For example, you can do:
class Server
def index
#user = User.new("Abiodun Shuaib")
haml :index
end
end
By doing this, you will add to Server method index.
Or you can do in such way(it's called Mixin):
module ActionNew
def index
#user = User.new("Abiodun Shuaib")
haml :index
end
end
class Server < Sinatra::Base
include ActionNew
get '/' do
index
end
end

Set Up for RSpec in a Sinatra modular app

This is my first attempt with Sinatra. I built a simple classic app, set up RSpec for it, and got it working. Then, I tried to go modular, in a MVC fashion. Even though the app works in the browser, RSpec throws a NoMethodError. I've read Sinatra docs regarding RSpec, also searched a lot here in SO, but I can't find where the bug is. Any clue?
Thank you very much in advance.
Here are my relevant files:
config.ru
require 'sinatra/base'
Dir.glob('./{app/controllers}/*.rb') { |file| require file }
map('/') { run ApplicationController }
app.rb
require 'sinatra/base'
class ZerifApp < Sinatra::Base
# Only start the server if this file has been
# executed directly
run! if __FILE__ == $0
end
app/controllers/application_controller.rb
class ApplicationController < Sinatra::Base
set :views, File.expand_path('../../views', __FILE__)
set :public_dir, File.expand_path('../../../public', __FILE__)
get '/' do
erb :index
end
end
spec/spec_helper.rb
require 'rack/test'
# Also tried this
# Rack::Builder.parse_file(File.expand_path('../../config.ru', __FILE__))
require File.expand_path '../../app.rb', __FILE__
ENV['RACK_ENV'] = 'test'
module RSpecMixin
include Rack::Test::Methods
def app() described_class end
end
RSpec.configure { |c| c.include RSpecMixin }
spec/app_spec.rb
require File.expand_path '../spec_helper.rb', __FILE__
describe "My Sinatra Application" do
it "should allow accessing the home page" do
get '/'
expect(last_response).to be_ok
end
end
The error
My Sinatra Application should allow accessing the home page
Failure/Error: get '/'
NoMethodError:
undefined method `call' for nil:NilClass
# ./spec/app_spec.rb:5:in `block (2 levels) in <top (required)>'
I'm guessing you're following this recipe, correct?
The described_class in this line:
def app() described_class end
is meant to be the class under test, in this case ZerifApp. Try it like so:
def app() ZerifApp end
EDIT
It turns out the above answer is not correct about what described_class does. I assumed it was a placeholder -- actually it is an RSpec method that returns the class of the implicit subject, that is to say, the thing being tested.
The recipe at the link is misleading because of the way it recommends writing the describe block:
describe "My Sinatra Application" do
This is valid RSpec, but it does not define the subject class. Executing described_class in an example for this block will return nil. To make it work, replace the describe block:
describe ZerifApp do
Now described_class will return the expected value (ZerifApp)
https://pragprog.com/book/7web/seven-web-frameworks-in-seven-weeks
It has some source code to get some ideas from.
This has code example too. https://github.com/laser/sinatra-best-practices

Modular Sinatra App using Sinatra Reloader?

Hi if I had a 'main' sinatra file with the following code,
require 'sinatra'
require "sinatra/reloader"
class MyApp < Sinatra::Base
configure do
require "./rest/auth.rb"
register Sinatra::Reloader
also_reload '/rest/auth'
end
get '/' do
erb :home
end
end
And I wanted to put my authentication logic inside of /rest/auth.rb, how can I get /rest/auth.rb to reload in development mode? Must I put the configure block and require sinatra/reloader in every one of my controller files? I'd like for my controllers to inherit the settings of my main class. The code inside of auth.rb is as follows:
class MyApp < Sinatra::Base
set(:auth) do |*roles| # <- notice the splat here
condition do
unless logged_in?
session[:success_url] = request.path_info
redirect '/'
end
end
end
def logged_in?
current_user
end
def current_user
if session[:user_id]
u = User.find(:id=>"#{session[:user_id]}")
else
false
end
end
end
I need to restart the server for my changes to take place but I can throw that reload code in auth.rb's configure block though I wouldn't like to. Any ideas?
Try to rewrite like this
require 'sinatra/base'
require "sinatra/reloader"
class MyApp < Sinatra::Base
configure :development do
register Sinatra::Reloader
also_reload './rest/auth'
end
require "./rest/auth.rb"
get '/' do
erb :home
end
end

Sinatra tests always 404'ing

I have a very simple Sinatra app which I'm having trouble testing.
Basically, every single request test returns a 404 when I know from testing in the browser that the request works fine. Any ideas as to what the problem might be?
test_helper.rb:
ENV["RACK_ENV"] = 'test'
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'app'
Sinatra::Synchrony.patch_tests!
class Test::Unit::TestCase
include Rack::Test::Methods
end
app_test.rb
require 'test_helper'
class AppTest < Test::Unit::TestCase
def app
#app ||= Sinatra::Application
end
def test_it_says_hello
get "/"
assert_equal 200, last_response.status
end
end
app.rb
$: << 'config'
require "rubygems" require "bundler"
ENV["RACK_ENV"] ||= "development"
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
require ENV["RACK_ENV"]
class App < Sinatra::Base register Sinatra::Synchrony
get '/' do
status 200
'hello, I\'m bat shit crazy and ready to rock'
end
end
Gemfile
source :rubygems
gem 'daemons'
gem 'sinatra'
gem 'sinatra-synchrony', :require => 'sinatra/synchrony'
gem 'resque'
gem 'thin'
group :test do
gem 'rack-test', :require => "rack/test"
gem 'test-unit', :require => "test/unit"
end
Why can I not get this normally very simple thing working?
I had quite the same problem with only HTTP-404 coming in return.
I solved it with giving another return in the "app" function.
class IndexClassTest < Test::Unit::TestCase
def app
#app = Foxydeal #appname NOT Sinatra::Application
end
...
Also
Sinatra::Synchrony.patch_tests!
seems to be obsolete.
Under your app_test.rb do this instead of what you have now:
def app
#app ||= App.new
end
This will work with your your class style like you had it in the beginning, no need to switch to the non-class/modular style.
It may seem logical, but are your routes configured correctly? If a route isn't correctly configured, it'll throw 404 errors left and right.
Figured it out.
app.rb
$: << 'config'
require "rubygems" require "bundler"
ENV["RACK_ENV"] ||= "development" Bundler.require(:default,
ENV["RACK_ENV"].to_sym) require ENV["RACK_ENV"]
class App < Sinatra::Base
register Sinatra::Synchrony
end
get '/' do
status 200
'hello, I\'m bat shit crazy and ready to rock'
end
You may simply do this:
class AppTest < Test::Unit::TestCase
def app
Sinatra::Application
end
You can get a solid understanding of sinatra tests by reading Learning From the Masters: Sinatra Internals and Rack::Test

Webrat Mechanize outside of Rails

I'm trying to use Webrat in a standalone script to automate some web browsing. How do I get the assert_contain method to work?
require 'rubygems'
require 'webrat'
include Webrat::Methods
include Webrat::Matchers
Webrat.configure do |config|
config.mode = :mechanize
end
visit 'http://gmail.com'
assert_contain 'Welcome to Gmail'
I get this error
/usr/lib/ruby/gems/1.8/gems/webrat-0.6.0/lib/webrat/core/matchers/have_content.rb:57:in 'assert_contain': undefined method assert' for #<Object:0xb7e01958> (NoMethodError)
assert_contain and other assertions are methods of test/unit, try to require it and use webrat from inside a test method:
require 'test/unit'
class TC_MyTest < Test::Unit::TestCase
def test_fail
assert(false, 'Assertion was false.')
end
end
anyway i haven't tested it but I have a working spec_helper for rspec if this can interest you:
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
require 'spec/rails'
require "webrat"
Webrat.configure do |config|
config.mode = :rails
end
module Spec::Rails::Example
class IntegrationExampleGroup < ActionController::IntegrationTest
def initialize(defined_description, options={}, &implementation)
defined_description.instance_eval do
def to_s
self
end
end
super(defined_description)
end
Spec::Example::ExampleGroupFactory.register(:integration, self)
end
end
plus a spec:
# remember to require the spec helper
describe "Your Context" do
it "should GET /url" do
visit "/url"
body.should =~ /some text/
end
end
give it a try I found it very useful (more than cucumber and the other vegetables around) when there is no need to Text specs (features) instead of Code specs, that I like the most.
ps you need the rspec gem and it installs the 'spec' command to execute your specs.

Resources