what is the proper way for testing create action in rails RESTfull controller? - ruby-on-rails-4.2

I have a users_controller.rb file in which the create action is defined as:-
def create
#user = User.new(user_params)
if current_user.g_admin?
#user.role = 'c_admin'
elsif current_user.c_admin?
#user.role = 'c_user'
end
#user.admin_provisioned = true
authorize #user
respond_to do |format|
if #user.save
format.html { redirect_to authenticated_root_url, notice: 'User was successfully created and email has been sent.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Now, I would like to write test for this method reflecting all the behaviour in this method. I'm completely new to testing, so detailed and standard way for writing test will be accepted as answer. The version to rspec is 3.4. Happy coding.

So the following way you could test this with rspec and capybara. For the fill in part you have to use the input elements that you have on your page.
describe "let an guest create a user account" do
fill_in :user_object, with: "value"
click_button "Save User"
expect(page).to have_content("User was successfully created and email has been sent.")
end
describe "let an guest try to create an account with invalid data" do
fill_in :user_object, with: "invalid value"
click_button "Save User"
expect(page).to_not have_content("User was successfully created and email has been sent.")
expect(page).to have_content("content from the :new page")
end

Related

NetSuite beforeload cancel action

I have a userevent beforeload that conditionally removes print buttons. If users are in the list view they are still able to print from that menu. So I was wondering if anyone knows of a way to either intercept the request and redirect or notify them, or even change which pdf template is used.
Here is my code snippet:
if (scriptContext.type === scriptContext.UserEventType.PRINT) {
if(status == 2){
log.debug({
title: 'Trying to Print Approved PO',
details: status
});
return true;
}
else{
log.debug({
title: 'Trying to Print UnApproved PO',
details: status
});
//code here to redirect users, notify them of issue or change to different pdf template
return false;
}
}
While not ideal, I just threw an error and didn't catch it.
throw 'This error is a result of trying to print a PO that has not been approved.';
You can add checkbox field on the UE beforeLoad event and set the value true/false if the user can/can't generate the pdf. Then control the new field on the freemarker AdvPDF and instead of print the content, you can show a message if the user can't generate the pdf.
var field = objForm.addField({
id: 'custpage_allow_access',
type: serverWidget.FieldType.CHECKBOX,
label: 'Allow access'
});
field.defaultValue = "F";
field.updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN
});

Only first test succeeds running Spock suite with setupSpec()

I've been experimenting with Geb/Spock for testing some web applications but have hit an issue that I cannot seem to figure out.
I have a test class with a setupSpec() fixture method that calls a login method defined in AuthenticationSpec, and then a bunch of other methods that assert various things on this page:
class TestThisPage extends AuthenticationSpec {
def setupSpec() {
loginComplete("some user ID", "some password")
assert page instanceof ThisPage
}
def "Verify some link's text is correct"() {
when: "The user is at this page"
then: "The this specific link's text is correct"
assert someLink.text().equalsIgnoreCase("I am some text")
}
def "Verify that the correct user name is displayed"() {
when: "The user is signed in and at this page"
then: "The signed-in user's display name appears correctly on the page"
assert signInText.equalsIgnoreCase("Signed in as: some user ID")
}
def "Verify this page's copyright"() {
when: "The user is redirected to this page"
then: "The copyright is correct"
assert legalInfo.text().trim().equalsIgnoreCase("Some copyright text here")
}
}
Now when I run TestThisPage as a test suite, only the first test case (after the setupSpec() method) passes, all the rest fail with: groovy.lang.MissingPropertyException: Unable to resolve <some content identifier specified on ThisPage>
I know my content is defined correctly:
class ThisPage extends Page {
static at = {
title == "This page"
}
static content = {
someLink(to: SomeOtherPage) {$("a[href='someOtherPage.jsp'")}
signInText {loginInfo.find("#static-label").text().trim()}
}
}
and I can switch the order of the test methods and the first one will always pass, even if it failed the last run. If I run these test methods as a single unit test, they all pass too.
The only way I have gotten this to work is if I add at ThisPage to the when or given block. I guess it makes sense to explicitly set the page to ThisPage in each test method, but why, when running the entire class as a test suite, does only the first test method pass (even without the at ThisPage)?
Each subsequent test method does not know about the page you are on.
You can create a shared instance of the page which can then be accessed by each of your tests within the same spec:
class TestThisPage extends AuthenticationSpec {
#Shared ThisPage thisPage
def setupSpec() {
thisPage = loginComplete("some user ID", "some password")
assert page instanceof ThisPage
}
def "Verify some link's text is correct"() {
when: "The user is at this page"
then: "The this specific link's text is correct"
assert thisPage.someLink.text().equalsIgnoreCase("I am some text")
}
def "Verify that the correct user name is displayed"() {
when: "The user is signed in and at this page"
then: "The signed-in user's display name appears correctly on the page"
assert thisPage.signInText.equalsIgnoreCase("Signed in as: some user ID")
}
def "Verify this page's copyright"() {
when: "The user is redirected to this page"
then: "The copyright is correct"
assert thisPage.legalInfo.text().trim().equalsIgnoreCase("Some copyright text here")
}
}

control not entering format.html block

My controller method is like:
def forcefully_logout
process_license_pool_obj = Vendor::ProcessLicensePool.new(#user.vendor)
#user.authentication_token = ''
if #user.save
if process_license_pool_obj.update_license_pool?(false, #user.id.to_s, #user.vendor_id.to_s)
respond_to do |format|
format.html do
redirect_to license_management_vendor_url(#user.vendor_id), notice: 'User was successfully logged-out and license has been released.'
end and return
end
end
end
respond_to do |format|
format.html { redirect_to license_management_vendor_url(#user.vendor_id), warn: 'Unable to forcefully logout user, contact admin.' }
end
end
and the route for this method is as:-
resources :users, except: [:create] do
member { delete 'forcefully_logout', to: 'users#forcefully_logout' }
end
Although the method is working properly, but it gives error for "missing template" and the controll doesn't enters the 'format.html' block means instead of redirecting the method tries to render template. In server log the message for this request is something as "started delete and processing by this method as html" (since the request is also of html type) but redirect_to is not hit. What is the possible reason for this problem is this rails issue or am i missing some concept regarding request object. The request is of "delete" type. Thanks.
Actually the "and return" statement after "format.html" block was causing the flow not to enter 'format.html' block, the working code is as:
def forcefully_logout
process_license_pool_obj = Vendor::ProcessLicensePool.new(#user.vendor)
#user.authentication_token = ''
if #user.save
if process_license_pool_obj.update_license_pool?(false, #user.id.to_s, #user.vendor_id.to_s)
respond_to do |format|
format.html do
redirect_to license_management_vendor_url(#user.vendor_id), notice: 'User was successfully logged-out and license has been released.' and return
end
end
end
end
respond_to do |format|
format.html { redirect_to license_management_vendor_url(#user.vendor_id), warn: 'Unable to forcefully logout user, contact admin.' }
end
end

How do I add a custom form for my collection_action/controller?

I have the following:
collection_action :new, :method => :post do
begin
user = User.find_by_email(params[:email])
if user
UserPermission.create(:user_id => user.id,
:permission => UserPermission::SUPPORT,
:creator => current_user)
end
rescue ActiveRecord::RecordNotFound
flash[:warn] = 'User not found'
end
redirect_to admin_support_users_path, notice: 'Support user added.'
end
form do |f|
f.inputs do
f.input :email
end
end
action_item only: [:index], :method => :post do
link_to 'Add Support User', new_admin_support_user_path
end
The above works in the sense that no error is thrown. The support users page loads and I'm able to click the Add Support User button. However, 'Support user added.' is immediately shown. The Add Support User button does not take me to a form to enter an email. How do I add/create/use a form that passes an email parameter to my collection_action?
I'm new to activeadmin and documentation is sparse, so any help is appreciated. Thanks.
Figured it out. I'll try to explain as I understand it. And my initial question may have been unclear. The reason I was getting the, 'Support user added.' message is because I was updating the wrong method. The method above should have been the :create controller method, not the :new controller method. :new uses HTTP GET, which is why it would go directly to the redirect. :create accepts an HTTP POST. So, instead, I have the following:
def create
begin
user = User.find_by_email(params[:email])
if user
UserPermission.create(:user_id => user.id,
:permission => UserPermission::SUPPORT,
:creator => current_user)
end
rescue ActiveRecord::RecordNotFound
flash[:warn] = 'User not found'
end
redirect_to admin_support_users_path, notice: 'Support user added.'
end
def new
render 'new.html.arb', :layout => 'active_admin'
end
And this correctly creates a nice looking active admin form, accepting an email parameter.
You just need to add another action--just like a normal resource needs separate actions for create and new. Your 'new' action can render a custom form either inline or in a separate partial, as shown here:
http://www.activeadmin.info/docs/5-forms.html
That said, I'm not sure I understand why you need a custom action. Is this in your User resource file in active admin? If so you can just use the default new user action and include the current user in the form as a hidden variable as the creator. If this is not in your User resource active admin file then you probably need one.

Authlogic edit_password_reset_url in Functional / Integration Tests

I am trying to implement some tests to validate the behavior for Authlogic password resets as explained in http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/
I am using Authlogic, Shoulda, Webrat and Factory Girl and here's my test:
require 'test_helper'
class PasswordResetTest < ActionController::IntegrationTest
setup :activate_authlogic
context "A registered user" do
setup do
#reggie = Factory(:reggie)
end
should "not allow logged in users to change password" do
visit signin_path
fill_in 'Email', :with => #reggie.email
fill_in 'Password', :with => #reggie.password
click_button 'Sign In'
assert_equal controller.session['user_credentials'], #reggie.persistence_token
visit change_password_path
assert_equal account_path, path
assert_match /must be logged out/, flash[:notice]
visit signout_path
assert_equal controller.session['user_credentials'], nil
visit change_password_path
assert_equal change_password_path, path
end
should "allow logged out users to change password" do
visit signout_path
assert_equal controller.session['user_credentials'], nil
visit change_password_path
assert_template :new
fill_in 'email', :with => #reggie.email
click_button 'Reset my password'
assert_match /Please check your email/, flash[:notice]
assert !ActionMailer::Base.deliveries.empty?
sent = ActionMailer::Base.deliveries.first
assert_equal [#reggie.email], sent.to
assert_match /Password Reset Instructions/, sent.subject
assert_not_nil #reggie.perishable_token
#TODO
p "Perishable Token #{#reggie.perishable_token}"
assert_match assigns[:edit_password_reset_url], sent.body
end
end
end
In the last 2 lines of the test, I am trying to make sure the link sent out has the right perishable_token and it always comes up different between the printed Perishable Token and the token in the link sent out.
How should I test this behavior?
Thanks, Siva
Careful. Authlogic is magic. Certain operations cause the User object to mutate and when it does, the perishable_token well, perishes (gets regenerated).
I wonder if your visit signout_path is really logging you out. Typically, if your UserSession is RESTful you'd have to issue an HTTP DELETE to the resource to actually delete the session. Just visiting the path (with a GET) won't delete the session unless you have an explicit route for it (mapping e.g. '/logout' to :controller => 'user_sessions', :action => 'destroy')
Change the line in notifier.rb to this:
body :edit_password_resets_url => edit_password_resets_url(user.perishable_token)

Resources