How to test a helper Grok view that makes a redirect - testing

I have a content type that needs to be modified in some way after calling a helper Grok view that checks some condition, makes some changes, sets a message and redirects to the original object.
my helper view only has a render method and I want to write some tests for it but I have no idea how to handle this.
I would like to check for an error message when some condition is not met, and for an info message when everything goes fine.
my code looks like this:
class MyHelperView(grok.View):
grok.context(IMyType)
grok.layer(IMyLayer)
grok.name('helper-view')
grok.require('my.permission')
def render(self):
variable = self.request.form.get('variable', None)
if not variable:
msg = _(u'Required input is missing.')
api.portal.show_message(message=msg, request=self.request, type='error')
else:
do_something()
msg = _(u'Information processed.')
api.portal.show_message(message=msg, request=self.request)
self.request.response.redirect(self.context.absolute_url())
when I call the view obviously I ended with a None object, as the view returns nothing. I don't know where to look for messages... request? response? any hint?

I would avoid using transaction commits in test code. The test framework is specifically designed to roll back the transactions at the end of each test. Your setUp override goes against this.
To check status messages in a unit test you should be able to do something like:
from Products.statusmessages.interfaces import IStatusMessage
IStatusMessage(request).show()
This is an adapter that adapts the request.

I ended up with test with a layer based on FunctionalTesting:
....
from plone.app.testing import TEST_USER_NAME
from plone.app.testing import TEST_USER_PASSWORD
from plone.testing.z2 import Browser
....
import transaction
...
class HelperViewTestCase(unittest.TestCase):
layer = FUNCTIONAL_TESTING
def setUp(self):
self.app = self.layer['app']
self.portal = self.layer['portal']
self.request = self.layer['request']
directlyProvides(self.request, IMyLayer)
with api.env.adopt_roles(['Manager']):
self.foo = api.content.create(self.portal, 'MyType', 'foo')
transaction.commit()
def test_response(self):
browser = Browser(self.app)
browser.handleErrors = False
browser.addHeader(
'Authorization',
'Basic {0}:{1}'.format(TEST_USER_NAME, TEST_USER_PASSWORD)
)
browser.open(self.foo.absolute_url())
browser.getControl('Do Something').click()
self.assertIn(
'Required input is missing.', browser.contents)
two things you need to check that make me spent some time debugging:
you must use transaction.commit() to reflect object creation on the ZODB
you must add an authorization header before trying to open the page
everything else is working.

Related

How to update Resource value in ReadyAPI/SoapUI dynamically by groovy?

my resource is in this format "testing/101/getCustomer/99"
Here I need to change "101" and "99" part dynamically by groovy so that I can run for multiple values in same test case. I looked into the ReadyAPI's built in feature, but it was not that helpful.
I also found this link, but it changed the resource in the entire project. The solution I am looking for is in test case level. As my each test case will have different url.
https://community.smartbear.com/t5/SoapUI-Open-Source/How-to-set-the-resource-path-at-run-time-while...
Any help will be appreciated.
Here is what I have tried so far
import com.eviware.soapui.impl.rest.RestResource
import java.io.*;
def project = testRunner.testCase.testSuite.getProject()
String restServiceName = "Resource name" (From the Rest Request Properties)
List<RestResource> ops = project.getInterfaces()[restServiceName].getOperationList()
log.info("ops ::"+ops);
log.info("ops size ::"+ops.size());
for (RestResource restResource : ops) {
String pathStr = restResource.getFullPath();
log.info("pathStr first-->"+restResource.getFullPath());
restResource.setPath("testing/101/getCustomer/99");
if (pathStr.contains("101"))
{
restResource.setPath("testing/101/getCustomer/99");
restResource.setPath(pathStr.replace("testing/101/getCustomer/99", "testing/50/getCustomer/99"));
}
}
you could use a testCase level property
first set the the value of res by groovy like below
def x=101
def y=99
def res="testing/$x/getCustomer/$y"
testRunner.testCase.setPropertyValue("resourc",res)
Now the testcase level property is set. It can be used as below wherever you want
${#TestCase#res}

POST a list to the API, update or create depending on the existence of that instance

I have a view which allows me to post multiple entries to a model. Currently if I add all new entries, they are added successfully. But if I add any entry for which the pk already exists, it naturally throws a serializer error and nothing gets updated.
I wish to write a method which will let me post multiple entries, but automatically either update an existing one OR add a new one successfully depending the existence of that instance.
The idea of a customized ListSerialzer is the closest thing I came across to achieve this but still not clear if I can do this.
Has anyone ever implemented anything like this ?
In views.py:
def post(self,request,format=None):
data = JSONParser().parse(request)
serializer = PanelSerializer(data=data,many=True)
if serializer.is_valid():
serializer.save()
return JsonResponse({"success":"true","content":serializer.data}, status=201)
return JsonResponse({'success': "false",'errorCode':"1",'errorMessage':serializer.errors}, status=400)
in serializers.py:
class PanelSerializer(serializers.ModelSerializer):
class Meta:
model = Panel
fields = ('pId','pGuid','pName', 'pVoltage', 'pAmperage','pPermission', 'pPresent', 'pSelf','pInfo')
def create(self, validated_data):
logger.info('Information incoming_1!')
print ("Atom")
return Panel.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.pId = validated_data.get('pId', instance.pId)
instance.pGuid = validated_data.get('pId', instance.pGuid)
instance.pName = validated_data.get('pName', instance.pName)
instance.pVoltage = validated_data.get('pVoltage', instance.pVoltage)
instance.pAmperage = validated_data.get('pAmperage', instance.pAmperage)
instance.pPermission = validated_data.get('pPermission', instance.pPermission)
instance.pPresent = validated_data.get('pPresent', instance.pPresent)
instance.pSelf = validated_data.get('pSelf', instance.pSelf)
instance.pInfo = validated_data.get('pInfo', instance.pInfo)
instance.save()
return instance
This is how the code stands as of now. I believe I will mainly need to either work on the update method of my serializer or first change it to a ListSerializer and write some custom logic again in the update method.

Rspec: Stubbing out a where statement in a controller test

I'm writing the following test:
let!(:city_areas) { FactoryGirl.create_list(:city_area, 30) }
before {
#city_areas = mock_model(CityArea)
CityArea.should_receive(:where).and_return(city_areas)
}
it 'should assign the proper value to city areas variable' do
get :get_edit_and_update_vars
assigns(:city_areas).should eq(city_areas.order("name ASC"))
end
to test the following method:
def get_edit_and_update_vars
#city_areas = CityArea.where("city_id = '#{#bar.city_id}'").order("name ASC").all
end
However, it fails out, saying that there's no method 'city_id' for nil:NilClass, leading me to believe it's still attempting to use the instance variable #bar.
How do I properly stub out this where statement to prevent this?
Why are you doing #city_areas = mock_model(CityArea) and then you never use #city_areas again?
I would test it this way:
inside the model CityArea create a named scope for this: where("city_id = '#{#bar.city_id}'").order("name ASC")
then in your controller spec you do
describe 'GET get_edit_and_update_vars' do
before(:each) do
#areas = mock('areas')
end
it 'gets the areas' do
CityArea.should_receive(:your_scope).once.and_return(#areas)
get :get_edit_and_update_vars
end
it 'assign the proper value to city areas variable' do
CityArea.stub!(:your_scope => #areas)
get :get_edit_and_update_vars
assigns(:city_areas).should eq(ordered)
end
end
and you should also create a spec for that new scope on the model spec
just a tip, you shouldn't use should_receive(...) inside the before block, use stub! inside before and use should_receive when you want to test that method is called
also, you shouldn't need to use factorygirl when testing controllers, you should always mock the models, the model can be tested on the model spec

How can I have a domain object's .save() method fail in an integration test?

For an integration test, I want to have a .save() intentionally in order to test the according else-condition.
My class under test does this:
From UserService.groovy:
User user = User.findByXyz(xyz)
if (user) {
// foo
if (user.save()) {
// bar
} else {
// I WANT TO GET HERE
}
}
The approaches I've tried so far failed:
What I've tried in in UserServiceTests.groovy:
def uControl = mockFor(User)
uControl.demand.save { flush -> null } // in order to test a failing user.save()
def enabledUser = userService.enableUser(u.confirmationToken)
uControl.verify()
// or the following:
User.metaClass.'static'.save = { flush -> null } // fails *all* other tests too
How can I get to the else-block from an integration test correctly?
You should almost never have a need for mocking or altering the metaclass in integration tests - only unit tests.
If you want to fail the save() call just pass in data that doesn't validate. For example all fields are not-null by default, so using def user = new User() should fail.
maybe you could try changing the 'validate' to be something else - by using the same meta class programming that u have shown .
That way, if the validate fails, the save will certainly fail
What I do in such cases:
I always have at least one field which is not null.
I simply don't set it and then call .save()
If you want to achieve this on an object already in the database, just load it using find or get and set one of the not null values to null and then try to save it.
If you don't have Config.groovy configured to throw exceptions on failures when saving it will not throw the exception, it simply won't save it [you can call .validate() upfront to determine whether it will save or not and check object_instance.errors.allErrors list to see the errors].

What am I doing wrong with this rspec helper test?

All I'm trying to do is spec how a one line helper method for a view should behave, but I'm not sure what kind of mock object, (if any) I should be creating if I'm working in Rails.
Here's the code for events_helper.rb:
module EventsHelper
def filter_check_button_path
params[:filter].blank? ? '/images/buttons/bt_search_for_events.gif' : '/images/buttons/bt_refine_this_search.gif'
end
end
And here's my spec code, in events_helper_spec.rb:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe EventsHelper do
#Delete this example and add some real ones or delete this file
it "should be included in the object returned by #helper" do
included_modules = (class << helper; self; end).send :included_modules
included_modules.should include(EventsHelper)
end
it "should return the 'refine image search' button if a search has been run" do
# mock up params hash
params = {}
params[:filter] = true
# create an instance of the class that should include EventsHelper by default, as the first test has verified (I think)
#event = Event.new
# call method to check output
#event.filter_check_button_path.should be('/images/buttons/bt_search_for_events.gif')
end
end
When I've looked through the docs here - http://rspec.info/rails/writing/views.html, I'm mystified as to where the 'template' object comes from.
I've also tried looking here, which I thought would point me in the right direction, but alas, no dice. http://jakescruggs.blogspot.com/2007/03/mockingstubbing-partials-and-helper.html
What am I doing wrong here?
Thanks,
Chris
You are not doing anything in that spec, just setting a stub, so it will pass, but hasn't tested anything.
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe EventsHelper do
it "should return the 'refine image search' button if a search has been run" do
# mock up params hash
params = {:filter => true}
helper.stub!(:params).and_return(params)
helper.filter_check_button_path.should eql('/images/buttons/bt_search_for_events.gif')
end
end
I'm running my test without spec_helper (Ruby 1.9)
require_relative '../../app/helpers/users_helper'
describe 'UsersHelper' do
include UsersHelper
...
end
Ah,
I asked this question on the rspec mailing list, and one kind soul (thanks Scott!) explained to me that there's a handy helper object for this, that you should use instead, like so:
Rails has its own helper function
params = {:filter => true}
helper.stub!(:params).and_return(params)
I've now updated the code like so:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe EventsHelper do
#Delete this example and add some real ones or delete this file
it "should be included in the object returned by #helper" do
included_modules = (class << helper; self; end).send :included_modules
included_modules.should include(EventsHelper)
end
it "should return the 'refine image search' button if a search has been run" do
# mock up params hash
params = {}
params[:filter] = true
helper.stub!(:filter_check_button_path).and_return('/images/buttons/bt_search_for_events.gif')
end
end
And it's working. Huzzah!