uninitialized constant error with SitePrism page - ruby

I've added this to my spec_helper:
require 'capybara'
require 'capybara/dsl'
require 'capybara/rspec'
require 'selenium-webdriver'
require 'site_prism'
And my page is this:
class AboutPage < SitePrism::Page
end
My rspec is this:
require_relative 'spec_helper'
describe 'About Page' do
it "test" do
about = AboutPage.new
end
end
The error I keep getting is:
Failures:
1) About Page test
Failure/Error: about = AboutPage.new
NameError:
uninitialized constant AboutPage
# ./about_spec.rb:6:in `block (2 levels) in '

If AboutPage is not in the root path of controller, you must call it with a namespace like:
about = SomeNameSpace::AboutPage.new

It looks like I needed to add to my spec_helper.rb:
require_relative about_page.rb
All pages you are using in your spec files have to be required before the can be used.

If all of your site prism objects are in spec/page_objects, using rspec, you could add this line to rails_helper.rb
Dir[Rails.root.join('spec/page_objects/**/*.rb')].each { |f| require f }
This will automatically require about_page.rb and any other page objects, including subfolders.

Related

How do I reference a method in a different class from a method in another class?

I have a module and class in a file lib/crawler/page-crawler.rb that looks like this:
require 'oga'
require 'net/http'
require 'pry'
module YPCrawler
class PageCrawler
attr_accessor :url
def initialize(url)
#url = url
end
def get_page_listings
body = Net::HTTP.get(URI.parse(#url))
document = Oga.parse_html(body)
document.css('div.result')
end
newpage = PageCrawler.new "http://www.someurl"
#listings = newpage.get_page_listings
#listings.each do |listing|
bizname = YPCrawler::ListingCrawler.new listing['id']
end
end
end
Then I have another module & class in another file lib/crawler/listing-crawler.rb that looks like this:
require 'oga'
require 'pry'
module YPCrawler
class ListingCrawler
def initialize(id)
#id = id
end
def extract_busines_name
binding.pry
end
end
end
However, when I try to run this script ruby lib/yp-crawler.rb which executes the page-crawler.rb file above and works without the YPCrawler call, I get this error:
/lib/crawler/page-crawler.rb:23:in `block in <class:PageCrawler>': uninitialized constant YPCrawler::ListingCrawler (NameError)
The issue is on this line:
bizname = YPCrawler::ListingCrawler.new listing['id']
So how do I call that other from within my iterator in my page-crawler.rb?
Edit 1
When I just do `ListingCrawler.new listing['id'], I get the following error:
uninitialized constant YPCrawler::PageCrawler::ListingCrawler (NameError)
Edit 2
Here is the directory structure of my project:
Edit 3
My yp-crawler.rb looks like this:
require_relative "yp-crawler/version"
require_relative "crawler/page-crawler"
require_relative "crawler/listing-crawler"
module YPCrawler
end
In your yp-crawler.rb file, based on the structure that you posted, you should have something like:
require 'yp-crawler/version'
require 'crawler/listing-crawler'
require 'crawler/page-crawler'
Try this, in your yp-crawler.rb add the line:
Dir["#{File.dirname(__FILE__)}/crawler/**/*.rb"].each { |file| load(file) }
That should automatically include all files in your /crawler directory at runtime. Might want to do the same for the other directories.
Let me know if that helps :)

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

uninitialized constant BikeShare (NameError)

I'm trying to implement some simple testing in rspec for a gem I'm writing. When I comment out describe BikeShare do down to end and run the file, the file loads in and runs successfully. I'm sure it's something tiny I'm missing.
My test file is really simple and looks like this:
require 'spec_helper'
describe BikeShare do
it "should run" do
# response = BikeShare.new
# response.should_be present
end
end
When run, I get the error uninitialized constant BikeShare (NameError) at line 3.
My bikeshare.rb file looks like this, fairly simple:
class BikeShare
def initialize
response = JSON.parse(open("http://bayareabikeshare.com/stations/json").read)
#response = response["stationBeanList"]
end
def get_last_station
#response.last["id"]
end
end
My Rakefile looks like this:
require 'rubygems'
require 'bundler'
Bundler.setup
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |spec|
# spec.libs << 'lib' << 'spec'
spec.pattern = 'spec/*_spec.rb'
end
task :default => :spec
Your tests arent aware of BikeShare.
You need to require the file that defines your BikeShare class. I dont use rspec but I think that you normally set up your testing environment in spec_helper.rb.

Unable to make a rake-tasks file and make it work properly

I decided to create a rake tasks for my Sinatra project and not to use the ready ones.
#Rakefile
require 'rake/testtask'
require 'rake/clean'
Dir.glob("tasks/*.rake").each { |r| import r }
#/tasks/seed.rake
require 'rubygems'
require 'bundler'
Bundler.require
require 'mongoid'
require_relative '../models/user'
namespace :db do
task :seed do
puts 'Creating a user....'
user1 = User.new email: "email1#gmail.com", password: "test123"
user1.save!
puts 'User has been created.'
end
end
#user.rb
require 'bcrypt'
require 'digest/md5'
require 'openssl'
class User
include Mongoid::Document
include Mongoid::Timestamps
#.........
#gemfile (partly)
source 'http://rubygems.org'
gem 'bcrypt-ruby', require: 'bcrypt'
And I've got the error of "Creating a user....
rake aborted!
undefined method `create!' for BCrypt::Password:Class
/home/alex/ruby_projects/service/models/user.rb:47:in `password='"
where #47 looks like
def password= pass
self.hashed_password = BCrypt::Password.create! pass, cost: 10
end
Note that in normal development everything works just fine. So I missed to require a file I think.
Your thoughts?
p.s. Even if I put
require 'bcrypt'
require 'digest/md5'
require 'openssl
to /tasks/seed.rake the error remains.
It appears you are using a non-existant method from BCrypt::Password. According to the docs, there is only a .create method and no .create! method. Switch to BCrypt::Password.create and it should work.
def password= pass
self.hashed_password = BCrypt::Password.create pass, cost: 10
end

Sinatra + Rspec2 - Use Sessions/Helpers?

I am trying to test my Sinatra app using Rspec2 but I can't get access to sessions or helper methods in my tests.
spec_helper:
require File.dirname(__FILE__) + "/../myapp.rb"
require 'rubygems'
require 'sinatra'
require 'rack/test'
require 'rspec'
require 'factory_girl'
set :environment, :test
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
def app
Sinatra::Application
end
app_spec.rb:
require File.dirname(__FILE__) + "/../spec_helper.rb"
describe 'Something' do
it "should do something" do
session["aa"] = "Test"
end
end
This throws an error, can't find session variables. Similarly I can't use helper methods which are defined in my app.
I run my tests using rspec specs/app_spec/app_spec.rb.
What am I doing wrong?
Assuming you've got your specs and spec helper in the /spec dir, then this line should go at the top of your spec:
require_relative "./spec_helper.rb"
I also like to use File.expand_path and File.join as it's more reliable than doing it yourself, e.g.
require File.dirname(__FILE__) + "/../spec_helper.rb"
becomes
require_relative File.expand_path( File.join File.dirname(__FILE__), "/../spec_helper.rb" )
Also, I don't tend to require "sinatra", the app has that. If you're missing bits from sinatra then maybe, but I add things like this instead through rack:
ENV['RACK_ENV'] = 'test'
Finally, if your Sinatra app is using the modular style then you'll have to include it too. I do this at the top of a spec, for example:
describe "The site" do
include Rack::Test::Methods
include MyApp
let(:app) { MyApp.app }
YMMV. Let us know if any of this works.
A different test to try:
before(:all) { get "/" }
subject { last_response }
it { should be_ok }

Resources