How to Include Rails views helper in Capybara steps - capybara

I have a step definition:
Then(/^I should see the total price of the products$/) do
# assumes all existing products are in the cart
total = Product.find(:all).inject { |sum, p| sum + p.price }
page.find(".total").should have_content number_to_currency(total)
end
This blows up with undefined method 'number_to_currency' for #<Cucumber::Rails::World:0xbef8d18> (NoMethodError)
I could emulate the "total" by emulating the behaviour of the number_to_currency helper, but I'd rather re-use the helper from Rails, because in this step I am not interested in the formatting, just that the total is calculated and rendered.
How do I include the NumberHelper or any view helper in capybara for access from step definitions?

The way I include helper into my cucumber testing here:
You create a file world.rb (or any name you want) under support folder. In my world.rb I define like this:
module Helper
include ProjectHelper
include ProductBacklogHelper
include ApplicationHelper
include Capybara::DSL
include Prickle::Capybara
end #end Module
World(Helper)
You should include the helper file that has "number_to_currency" function in world.rb
I hope this will help you

Related

Creating a Gem that adds a rails form helper

I'm creating a gem to add a new helper method for rails forms. My gem is a single file
lib/rails_json_field.rb
that looks like this:
require 'action_view/helpers'
require 'action_view/context'
require 'securerandom'
module ActionView
module Helpers
class FormBuilder
include ActionView::Helpers::FormTagHelper
include ActionView::Helpers::JavaScriptHelper
include ActionView::Context
def json_field_tag(method, options = {})
#function code here
end
end
end
end
ActiveSupport.on_load(:action_view) do
include ActionView::Helpers::FormBuilder
end
However when I use the method like so:
= f.json_field_tag(:some_method)
I receive the following error:
ActionView::Template::Error (undefined method `json_field_tag' for #<ActionView::Helpers::FormBuilder:0x007ffa84ab52a8>)
How do I make the method available on ActionView::Helpers::FormBuilder ?
You have defined the following class:
RailsJsonField::ActionView::Helpers::FormBuilder
You meant to monkeypatch the following class:
ActionView::Helpers::FormBuilder
That's why the error message is telling you the method is undefined; you have defined it within a class within your custom module, not within the specified class:
undefined method `json_field_tag' for #<ActionView::Helpers::FormBuilder
It's only defined in RailsJsonField::ActionView::Helpers::FormBuilder, so you get the above error.
If you want to properly monkeypatch the original code then you should look at the original code to ensure your code looks like their code:
module ActionView
module Helpers
class FormBuilder
def json_field_tag(method, options = {})
# function code here
end
end
end
end
It would be better to define this as an initializer in your Rails app, e.g., in config/initializers/json_field_tag.rb. Once you have the code working as a simple patch, then you can focus on developing it into a standalone gem that enhances ActionView.
After searching, I found a different gem that adds a FormBuilder method. I used their repo as a guide to structure my own. For others with this questions, you can view my repo and their repo here respectively:
https://github.com/dyeje/rails_json_field
https://github.com/Brantron/john_hancock

How to test a Rails helper that depends on another Rails helper?

I am writing an RSpec spec to test a Rails helper. The problem is that the helper method that I'm testing depends on a method defined in a different helper. It may be a code smell to me, but I'm adding tests for legacy code and am not at a point where I can refactor. How can I test this Rails helper?
module FancyHelper
def fancy_method
html = "hello"
html << another_fancy_method
html
end
end
module OtherHelper
def another_fancy_method
"world"
end
end
require "spec_helper"
describe FancyHelper do
describe "#fancy_method" do
it "does what it's supposed to" do
helper.fancy_method.should match("hello")
# NoMethodError: undefined method `another_fancy_method'
end
end
end
This is what stubs are for. When testing your helper that depends on the other helper, you will want to stub the other helper to get a predictable value and complete the test.
EDIT: https://www.relishapp.com/rspec/rspec-mocks/docs/method-stubs thanks grantovich for the newer link.

Reskinning ActiveAdmin using Bootstrap

I want to re-skin ActiveAdmin using a Bootstrap template theme. However I need to change the layout of the page to suit.
Is it possible to override the layout of ActiveAdmin to suit what I want? It looks different to normal rails conventions - I'd rather just accomplish it using a regular template and then yield the parts of the content that I need in the order that I need them.
Ive done something similar before. Check out this Gist https://gist.github.com/bigfive/6017435
Essentially you patch the active admin base controller to use your new layout by overriding their :determine_active_admin_layout method
# config/initializers/active_admin_patch.rb
module ActiveAdmin
class BaseController
def determine_active_admin_layout
'active_admin_reskin'
end
end
end
Then in your active_admin_reskin layout you can call methods on the Arbre view_factory like so
view_factory[#{params[:action]}_page"].new(Arbre::Context.new(assigns, self)).send(:build_header)
In the gist(https://gist.github.com/bigfive/6017435) Ive made a little view helper for making it easy to call those methods.
Have a look through the active admin source code to see which methods are available to you on various Arbre documents, especially here: https://github.com/gregbell/active_admin/blob/master/lib/active_admin/views/pages/base.rb
Once the markup is changed the way you like, you can #include 'bootstrap' into your active_admin.css.scss file that the generator created and go nuts.
A simple answer would be putting
#import "bootstrap";
into active_admin.css.scss
Officially, its not supported for now https://github.com/gregbell/active_admin/issues/1027
Depending on what version of AA you are using.
(0.6.0 < commit:ec9996406df5c07f4720eabc0120f710ae46c997):
Include your scss, but encapsulate your css selectors in the body.active_admin group. Furthermore, specificity is important, so if you want to override the default styling of AA, you may need to ensure you are overriding the full selector to get the behavior you want.
If you want to find these styles to override them, take a look at AA's stylesheets to see how they style the site be default. Simply include your custom styling after the the AA stylesheet is included.
After commit:ec9996406df5c07f4720eabc0120f710ae46c997
The namespacing of stylesheets has been removed recently, and I have not throroughly tested the implication yet.
BigFive's accepted answer worked for me at the beginning but then produced some bugs when rendering custom partials or when rendering errors in forms.
Inspired by his approach I switched to overriding the individual methods that AA uses to dynamically generate the layout (as AA doesn't use a static layout file that can be easily modified).
You can find the available methods in the source code, but it's pretty self-explanatory and begins in the html element.
Example:
To add some classes and reorganize the elements:
You can put your style in:
assets/stylesheets/active_admin.css.scss
And your html description in:
config/initializers/active_admin_patch.rb:
module ActiveAdmin
module Views
class Header
alias_method :original_build_site_title, :build_site_title
alias_method :original_build_global_navigation, :build_global_navigation
alias_method :original_build_utility_navigation, :build_utility_navigation
def build_site_title
div class: "side_bar_top" do
original_build_site_title
end
end
def build_global_navigation
div class: "side_bar_content" do
original_build_global_navigation
end
end
def build_utility_navigation
div class: "side_bar_footer" do
original_build_utility_navigation
end
end
end
module Pages
class Base
alias_method :original_build, :build
# This should be the same as add_classes_to_body but for the html main element
def add_classes_to_html_tag
document.add_class(params[:action])
document.add_class(params[:controller].gsub('/', '_'))
document.add_class("active_admin")
document.add_class("logged_in")
document.add_class(active_admin_namespace.name.to_s + "_namespace")
end
def build(*args)
original_build
add_classes_to_html_tag
end
def build_page
within #body do
div id: "wrapper" do
div id: "details_view" do
build_title_bar
build_page_content
#build_footer
end
div id: "master_view" do
build_header
end
end
end
end
end
end
end
end

Multiple Rails Helpers w/ Same Method Name

I have two different helper files (photos_helper & comments_helper) w/ that have a method named actions_for. How can I explicitly call which helper method that I need? I know that I could just rename one of them but I would prefer to keep them the same. I tried PhotosHelper::actions_for but that doesn't seem to work.
In Rails 3 all helpers are always (in Rails 3.1 a patch exists to selectively allow helpers again) included. What's happening behind the scenes:
class YourView
include ApplicationHelper
include UserHelper
include ProjectHelper
...
end
So depending on the order Rails includes them, any of your actions_for methods will be used. There is no way you can explicitly chose one of them.
If you would have to explicitly call ProjectHelper.action_for, you could also name your methods project_action_for - simplest solution.
Make both of them a Class Method
module LoginsHelper
def self.your_method_name
"LoginsHelper"
end
end
AND
module UsersHelper
def self.your_method_name
"UsersHelper"
end
end
Then in View
LoginsHelper.your_method_name #Gives 'LoginsHelper'
AND
UsersHelper.your_method_name #Gives 'UsersHelper'

Adding Controller Macros in Rspec

Im trying to define some controller macros for Rspec. Im using rails 3 and have my macros defined in spec/support/macros/controller_macros.rb, that file looks like this:
module ControllerMacros
def self.login_admin
#code
end
end
in my spec helper I have:
config.include(ControllerMacros, :type => :controller)
So in my controller spec i just call login_admin in my admin tests but when ever i use the method i get
undefined local variable or method `login_admin' for #<Class:0xb6de4854> (NameError)
At first I assumed that controller_macros.rb wasn't being included but when I added a "puts" to the file but that showed the file was at least being executed.
I can't see anything wrong with my setup and copying the login_admin method into the describe block works fine so im not sure whats wrong with it.
Maybe I am late to that, but for new comers.
Here is a good examples of using macros:
http://osmose.6spot.com.br/2011/01/rails-resource-routing-spec-w-rspec/
when you include a module it's methods are visible inside examples.
But when you extend the module, it's methods are only visible outside examples.
It gives you ways to compose your macros for each situation.
Try
ControllerMacros.login_admin
or remove self from the method definition.
One line answer: Remove self from the method definition
Why? The methods of included modules are available in RSpec examples
The login_admin method defined in ControllerMacros will be available in your RSpec example as login_admin
To Be Specific:
Rewrite spec/support/macros/controller_macros.rb as
module ControllerMacros
def login_admin
#code
end
end
Then tell Rspec to include the Macros
config.include(ControllerMacros, :type => :controller)

Resources