I'm trying to test that logged in users can log out on my Django site with Lettuce, Selenium and lettuce_webdriver.
In my terrain.py I have:
@before.all
def setup_browser():
profile = webdriver.FirefoxProfile()
profile.set_preference('network.dns.disableIPv6', True)
world.browser = webdriver.Firefox(profile)
world.client = Client(HTTP_USER_AGENT='Mozilla/5.0')
And then when I 'login':
@step(r'I am logged in as "(\w*)"')
def log_in(step, name):
world.client.login(username=name, password=name)
And I go to my site:
And I go to "localhost:8000"
I find a link called "Logout ?" that goes to "/logout"
@step(r'I find a link called "(.*?)" that goes to "(.*?)"$')
def find_link(step, link_name, link_url):
print(world.browser.page_source)
elem = world.browser.find_element_by_xpath(r'//a[@href="%s"]' % link_url)
eq_(elem.text, link_name)
But my page_source shows I am not logged in. This kind of makes sense...in that client
and browser
aren't talking to each other. But is this possible, or do I need to login 'manually' by clicking links with selenium etc?
I'd like to do this:
world.browser.page_source = world.client.get(world.browser.current_url).content
But page_source can't be changed. Can I feed Selenium from django's client some how?
Edit: Following Loius' advice below, my 'I am logged in as ...' step is as below. I added the if/else to just check my suspicions. My client is still setup as above (see setup_browser
step above)
@step(r'I am logged in as "(\w*)"')
def log_in(step, name):
world.client.login(username=name, password=name)
if world.client.cookies:
session_key = world.client.cookies["sessionid"].value
world.browser.add_cookie({'name':'sessionid', 'value':session_key})
world.browser.refresh()
else:
raise Exception("No Cookies!")
All the advice I've seen is to login first. Without my check, I get this:
Scenario: Logged in users can logout # \gantt_charts\features\index.feature:12
Given I am logged in as "elsepeth" # \gantt_charts\features\steps.py:25
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\lettuce\core.py", line 144, in __call__
ret = self.function(self.step, *args, **kw)
File "D:\Django_Projects\gAnttlr\gantt_charts\features\steps.py", line 27, in log_in
session_key = world.client.cookies["sessionid"].value
KeyError: 'sessionid'
I've not tried doing exactly what you are trying to do but I've done something similar. What you need to do is set a cookie like this on your Selenium instance after you've logged into your Django site with your Client
instance:
driver.add_cookie({'name': 'sessionid', 'value': session_key})
The name should be equal to your SESSION_COOKIE_NAME
setting on the Django site (sessionid
is the default). You need to figure out the value of session_key
.
You can obtain it from a Client
instance like this:
session_key = client.cookies["sessionid"].value
Note that Selenium won't be able to set the cookie for some browsers if SESSION_COOKIE_SECURE
is True
. You should have this setting be True
for your production server but if you want your Selenium tests to set your session cookie, then you have to make it False
for testing.
Once your Selenium instance has the cookie, it will look to Django as if you had logged into it with Selenium. As I said, I do something similar in my test suites. (I use something else than Client
but the principle is the same.)