0👍
In selenium we must use the URL of the testing server by default this is localhost, to enable access to an external accessible server address which is the hosting docker container’s address we need to use the server machine’s ip address,
So set as below,
class BaseTestCase(StaticLiveServerTestCase):
"""
Provides base test class which connects to the Docker
container running Selenium.
"""
host = '0.0.0.0' # Bind to 0.0.0.0 to allow external access
@classmethod
def setUpClass(cls):
super().setUpClass()
# Set host to externally accessible web server address
cls.host = socket.gethostbyname(socket.gethostname())
reference here
27👍
This error message…
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
…implies that an illegal attempt was made to set a cookie under a different domain than that of the current document.
Details
As per the HTML-Living Standard Specs a Document Object
may be categorized as a cookie-averse Document object in the following circumstances :
- A Document that has no
Browsing Context
. - A Document whose URL’s scheme is not a network scheme.
Deep Dive
As per Invalid cookie domain this error may occur if the current domain were to be example.com
, it would not be possible to add the cookie for the domain example.org
.
As an example:
-
Sample Code:
from selenium import webdriver from selenium.common import exceptions session = webdriver.Firefox() session.get("https://example.com/") try: cookie = {"name": "foo", "value": "bar", "domain": "example.org"} session.add_cookie(cookie) except exceptions.InvalidCookieDomainException as e: print(e.message)
-
Console Output:
InvalidCookieDomainException: https://example.org/
Solution
If you have stored the cookie from domain example.com
, these stored cookies can’t be pushed through the webdriver session to any other different domanin e.g. example.edu
. The stored cookies can be used only within example.com
. Further, to automatically login an user in future, you need to store the cookies only once, and that’s when the user have logged in. Before adding back the cookies you need to browse to the same domain from where the cookies were collected.
Example
As an example, you can store the cookies once the user havd logged in within an application as follows:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
driver.find_element_by_name("username").send_keys("abc123")
driver.find_element_by_name("password").send_keys("123xyz")
driver.find_element_by_name("submit").click()
# storing the cookies
pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
driver.quit()
Later if you want the user automatically logged-in, you need to browse to the specific domain /url first and then you have to add the cookies as follows:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
# loading the stored cookies
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
# adding the cookies to the session through webdriver instance
driver.add_cookie(cookie)
driver.get('http://demo.guru99.com/test/cookie/selenium_cookie.php')
Additional Consideration
It seems you are using chrome=77.0.3865.75. Ideally you need to ensure that:
- Selenium is upgraded to current levels Version 3.141.59.
- ChromeDriver is updated to current ChromeDriver v79.0.3945.36 level.
- Chrome is updated to current Chrome Version 79.0 level. (as per ChromeDriver v79.0 release notes)
Reference
You can find a detailed discussion in:
- Django Test Client post() returns 302 despite error on view's post()
- Django Request Framework 'ManyRelatedField' object has no attribute 'queryset' when modifying queryset in get_fields
- Can't Create Super User Django
2👍
I run into a similar problem while working with C#. I solved it by first setting the URL to the home page that does not need a user session and then setting the cookies and after that opening the page requiring a session. Here is the code
webDriver = new ChromeDriver(".");
String f = @"./scrapper/cookies.data";
String[] lines = File.ReadAllLines(f);
webDriver.Url = "https://myhomepage.com/";
foreach (String ln in lines)
{
String[] temp = ln.Split(';');
String name = temp[0];
String value = temp[1];
String domain = temp[2];
String path = temp[3];
DateTime expiry = DateTime.Now.AddDays(60);
if (!String.IsNullOrEmpty(temp[4]))
{
expiry = DateTime.Parse(temp[4]);
}
Boolean isSecure = Boolean.Parse(temp[5]);
Cookie cookie = new Cookie(name, value, domain, path, expiry);
webDriver.Manage().Cookies.AddCookie(cookie);
}
webDriver.Url = "https://target_page_requiring_session.php";
IWebElement tab3 = webDriver.FindElement(By.XPath("//*[@id='TabIDS_3']"));
tab3.Click();
1👍
I run into the same problem. My solution was simply to avoid setting domain
value (wich is optional, by the way) in the cookie.
class MyTestCase(StaticLiveServerTestCase):
host = os.environ['DJANGO_CONTAINER_NAME']
def test_logged_in(self):
self.client.login(username="integration", password="test")
self.selenium.get(self.live_server_url)
self.selenium.add_cookie({"name": settings.SESSION_COOKIE_NAME,
"value": self.client.cookies[settings.SESSION_COOKIE_NAME].value})
post = Post.objects.first()
self.selenium.get(f"{self.live_server_url}{reverse('post', args=(post.slug, ))}")
The main point here is to let the Django client (here self.client
) login and then copy its session cookie to a Selenium browser session, which should have already visited a page from your live server – in other words, first let the Selenium browser open a page, then set the cookie (skipping domain
) and then, the selenium browser is logged in.
- Inlineformset_factory create new objects and edit objects after created
- Invert boolean field in update operations with F()