Testing Rails helper that uses html escaping - ruby-on-rails

I'm attempting test a helper in Rails 4 that calls h(some_content) but when I run my unit tests I receive: undefined method 'h' for PageHelperTest.
How can I call h inside my helper, but still be able to execute the code in test? The code works correctly when hit through the website.

The h method is defined on ERB::Util which isn't available in the helper test. I fixed the issue by changing the helper to call ERB::Util.h(some_content)

Well I just hit similar issue.
However changing the helper just for the tests to pass is a NO NO to me.
So I tried around and this solved it (HOWEVER in Rails 3.2.22):
include ERB::Util
alias_method :html_escape, :h
I guess it's not the cleanest way (the alias, and what if another helper needs some other thing). So I guess there would be some better way (include some group of modules or whatnot) - but this one works.

Related

Ruby getting undefined Method error, and i am not sure if i fully understand how methods are working for my plugin

i am trying to create a plugin for Discourse, which is written in Ruby. As normal blank files my program is working perfect and without errors, but when i try to adapt my code into the plugin context i run into issues and i am not sure if i really understand how the whole idea with functions is meant to be.
I thought it would be smart to have more than just one file, to outsource functionality in different methods and require them in a kind of "main" file. For example getting tweets is one method in an extra file, sending tweets a different method in another file. In blank ruby code its working fine but when i try to integrate that into the plugin file structure i get the error
undefined method `my_method' for #<Plugin::Instance:0x00007f9004012fc0> (NoMethodError)
the files with the methods are in a lib directory and the "main" file which is called the plugin.rb is in the mainfolder
so i tried
require_relative 'lib/my_method'
and the other way
require_relative File.expand_path('../lib/my_method.rb', __FILE__)
but i still run into that error.
i have not defined any kind of classes or modules or something like that so the "method files" are literally starting with
def self.my_method
#my code here
end
Could that be the reason why i run into the error above? Why is it working as blank ruby code, but not when i try to run the plugin with rails s on my discourse instance?
I am still pretty new into ruby programming, so maybe my question seems a bit silly.
Here is the link which lead me threw the plugin creation:
https://meta.discourse.org/t/beginners-guide-to-creating-discourse-plugins-part-1/30515
Unfortunately, your understanding of methods is shallow. Basically, any method you declare in the global scope is added to the Object class as private method, so it is accessible everywhere in your objects cause they derive from Object class and in global scope because it is the scope of the Object class. If you declare method as self.method, you make it a method of main Object, because self refers to main, which is not the desired behaviour for you. To fix that issue, you should just remove self and write it like that:
def my_method
end
This way this method will be added to the Object class itself, not the main Object. There is a link on the article about methods in general. And another one on the toplevel scope behaviour. In this codepen you may observe the difference. Also, it may be useful for you to learn some Ruby before going on with your development. I suggest rubymonk. Another issue is your one-method files which is not the best practice for ruby code organization. Ruby is truly object-oriented language and if you need to have a bunch or even one general-purpose method, it is better to put it in a module or class to define its purpose and role in application, make it reusable and trackable, without global scope pollution.

Mock Rails 4 application config custom value

In Rails::Application, I add a custom configuration using...
config.x.cache_config = config_for(:cache)
In my tests, I want to see how code using this behaves depending on how the configuration is defined in cache.yml. To set the various conditions in my rspec tests, I want to do something like...
allow(Rails.application.config.x).to recieve(:cache_config).and_return({})
But this doesn't work. It gets an error stating
#<Rails::Application::Configuration::Custom ... > does not implement: cache_config
After much digging and testing in pry, I figured this out.
Short answer:
allow(Rails.application.config.x).to receive(:method_missing).with(:cache_config).and_return({})
Everything in this statement has to be exact except...
replace :cache_config with the name of your custom configuration key
replace {} in the and_return({}) with the mock value you want to set for the key
Longer answer:
If you want to dig into why this is, since it is not at all obvious, check out the code at...
Custom class in Rails::Application::Configuration
Creation of #x for custom configs in Rails::Application::Configuration
In case this helps anyone using Mocha, I ended up doing this in a helper
Rails.application.config.x.stubs(:my_config).returns(true)
yield
Rails.application.config.x.unstub(:my_config)
The method_missing trick above didn't work for some reason (guessing to do with differences in the way the stubbing is implemented), failing with an error message about the Configuration::Custom class not responding to method_missing the first time it was referenced for a different piece of config.
Adding to the above answer(s), if you want to stub nested config, then you have to make sure that you're allow-ing the second-last piece in the config to receive(:method_missing), as such:
allow(Rails.application.config.x.foo.bar).to receive(:method_missing).with(:foobar).and_return(:baz)
The above code stubs the Rails.application.config.x.foo.bar.foobar config to return :baz.

Ruby on Rails - undefined local variable or method - wice grid haml show_code

I am new to ruby on rails.
I am trying to get haml and wice_grid to work together. I am using this example as a model:
http://wicegrid.herokuapp.com/basics3
I get the error 'undefined local variable or method `show_code' for...'
In the file app/views/basics3/index.html.haml which you can see at the link above.
Am I missing a gem? In general, what is the best way to troubleshoot problems like this?
Thanks in advance-
Flex
EDIT: I found the definition for show_code. It's in a helper that I found in the unit tests for wice_grid.
https://github.com/leikind/wice_grid_testbed/blob/master/app/helpers/application_helper.rb
That said, I get more errors when I load it into my project. So the question becomes, how does the helper normally get included in my project?
show_code is a custom method created just for the example page you linked to. It just displays the code he has in his controller and his index and grid views. You don't need to call that method in your own application so just remove that line and you should be good.

Calling ERB without Rails: undefined method 'raw'

I am using the ERB engine to generate an offline HTML version of a page of my Rails website. The page shows great when shown by Rails, but I have trouble generating with ERB by myself (despite using the same ERB template).
First I was getting the error undefined method 't' and I solved it by replacing all <%=t(...)%> calls with <%=I18n.translate(...)%>.
Now I get undefined method 'raw'. Should I replace all <%=raw(...)%> calls with something else? If yes, what?
raw is defined as helper in actionpack/action_view library so that without rails you can't use it. But ERB templating shows its output without any escaping:
require 'erb'
#person_name = "<script>name</script>"
ERB.new("<%= #person_name %>").result # => "<script>name</script>"
And because of this for purpose of escaping there is ERB::Util#html_escape method
include ERB::Util
ERB.new("<%= h #person_name %>").result # => "<script>name</script>"
While #warhog 's answer will work, the include isn't necessary. It adds all the ERB::Util methods to the current class, which usually isn't desired and can cause unexpected side effects (if you had another h method for example). Instead just access the h method (or other helpers) using the ERB::Util class:
ERB.new("<%= ERB::Util.h #person_name %>").result

How to call 'time_ago_in_words' from a FunctionalTest?

I'm using 'time_ago_in_words' function in a view, and I need to test the output in the FunctionalTest.
But the test can not see 'time_ago_in_words' helper function.
What should I do in order to use these helper methods from FunctionalTests?
Include the ActionView::Helpers::DateHelper module in your test_helper.rb or test.rb files. And that's it, from the test console:
>> time_ago_in_words(3.minutes.from_now)
NoMethodError: undefined method `time_ago_in_words' for #<Object:0x3b0724>
from (irb):4
from /Users/blinq/.rvm/rubies/ruby-1.9.1-p376/bin/irb:15:in `<main>'
>> include ActionView::Helpers::DateHelper
=> Object
>> time_ago_in_words(3.minutes.from_now)
=> "3 minutes"
I added on rails_helper.rb
config.include ActionView::Helpers::DateHelper
and work's, thank's #jpemberthy!
I had a similar issue recently where I was trying to access this function from an API so I wrapped it in a gem called timeywimey. Check it out: https://github.com/onetwopunch/timeywimey#usage
It allows you to access this helper from anywhere in a Rails project as well as Sinatra, and a native ruby project.
What exactly are you trying to test? You shouldn't need to verify the behavior of time_ago_in_words itself, because that's covered by Rails' own tests. If you're testing one of your own helpers that uses time_ago_in_words, the output can be checked in a helper test (which inherits from ActionView::TestCase).
Functional tests are intended for verifying the behavior of controllers (what template they render, whether they allow access, redirect, etc) which can include checking for the presence of certain HTML tags (by id). I usually try to avoid using them to check the content of the tags.

Resources