Comments (20)
@josevalim @HashNuke I am thinking one of the simplest way, that would definitely work with all browsers and drivers, would be to add this metadata directly to the user agent string.
To have this working, we would have to
- Add a way to easily set the user agent, as there is not cross-browser way to do this
- Add a utility function to add some metadata to the UA string
- Add a utility function to extract the data from the UA string
2 and 3 are not really needed, but I think it is better for the end user to let the library take care of those details.
In the integration tests, we could then do something like
setup do
Hound.add_metadata_to_ua(%{"some-id" => "some-value"})
end
test "test something" do
my_metadata = conn |> get_request_header("user-agent") |> List.first |> Hound.extract_metadata_from_ua
end
The only drawback of this approach I can think of is that it could cause problems if someone is
relying too much on the user-agent string for something else.
What do you think?
from hound.
Here was my solution for creating a firefox profile. It was a bit of a chore, but once it is in place it works very well and you can customize with whatever preferences you need. I've even got it set up to use a locally-running proxy, but you may not need that.
To launch the session, create the profile with a Base64-encoded profile directory (zipped) and pass to desiredCapabilities:
b64 = MyApp.BrowserInstance.firefox(local_port, agent.user_agent)
Hound.start_session(%{firefox_profile: b64})
The BrowserInstance module which builds the Base64:
defmodule MyApp.BrowserInstance do
def firefox(local_port, user_agent) do
prefs = """
user_pref("general.useragent.override", "#{user_agent.string}");
user_pref("network.http.pipelining", true);
user_pref("network.http.pipelining.aggressive", true);
user_pref("network.http.pipelining.maxrequests", 8);
user_pref("network.http.pipelining.ssl", true);
user_pref("browser.cache.use_new_backend", 1);
user_pref("browser.tabs.animate", false);
user_pref("browser.display.show_image_placeholders", false);
user_pref("network.dns.disableIPv6", true);
user_pref("browser.startup.homepage", "about:blank");
user_pref("startup.homepage_welcome_url", "about:blank");
user_pref("startup.homepage_welcome_url.additional", "about:blank");
"""
if local_port do
settings = """
user_pref("network.proxy.type", 1);
user_pref("network.proxy.http", "localhost");
user_pref("network.proxy.http_port", #{local_port.port});
user_pref("network.proxy.ssl", "localhost");
user_pref("network.proxy.ssl_port", #{local_port.port});
user_pref("network.proxy.socks", "localhost");
user_pref("network.proxy.socks_port", #{local_port.port});
user_pref("network.proxy.share_proxy_settings", true);
"""
else
settings = ""
end
profile_dir = temp_path
File.mkdir(profile_dir)
settings_path = profile_dir <> "/user.js"
File.write!(settings_path, settings)
prefs_path = profile_dir <> "/prefs.js"
File.write!(prefs_path, prefs)
zip = profile_dir <> "/profile.zip"
files = File.ls!(profile_dir)
|> Enum.map(&String.to_char_list/1)
:zip.create(String.to_char_list(zip), files,[cwd: profile_dir])
{b64, _} = System.cmd("base64", [zip])
File.rm_rf!(profile_dir)
b64
end
defp temp_path do
rand = Base.encode32(:crypto.rand_bytes(20))
Path.join(System.tmp_dir, rand)
end
end
from hound.
@josevalim sorry. I didn't have IRCcloud on. I'm totally open to changes in Hound.
I read about ecto 2.0 sandboxes in a previous plataformatec blog post. I'll take tomorrow to read more and try Ecto 2.0 sandboxes and ping back. I'll have an informed opinion that way.
from hound.
The question is if drivers can let us customize the user agent.
from hound.
AFAIK, all drivers and browsers let us customize this, which is why I think it could be a good solution.
from hound.
If we can do this, it would be excellent. @tuvistavie can you investigate and send a PR to hound that allows us to configure the user agent when we start a session?
from hound.
@josevalim Sure, I am going to give it a try!
from hound.
@tuvistavie Adding meta data to UserAgent is a brilliant solution ~! 👍
from hound.
@HashNuke Do you know if there is a simple way to do this with Firefox? It is trivial for Chrome and PhantomJS, but for Firefox it seems we need to implement the profile, which seems to be quite a lot work for such a simple task.
from hound.
Awesome, if we can make this work for concurrent testing, things will be even easier from the Ecto/Phoenix integration side!
from hound.
@darksheik Thank you very much for sharing, this is really helpful!
Would you have the time to send a PR with your implementation and
possibly some tests?
If you don't have the time, just let me know and I will try to integrate
your solution into Hound.
Thank you ! 😄
from hound.
A bit swamped at the moment - This works well in my own Ubuntu/Mac infrastructure but I have been meaning to investigate whether I can do this without using the file system.
from hound.
@darksheik Thank you for posting details ~!
from hound.
After merging #94, we will have the possibility to add the user agent for all browsers:
ua = "whatever string we want"
# firefox
alias Hound.Firefox.Profile
profile = Profile.new |> Profile.set_user_agent(ua) |> Profile.dump
Hound.start_session(%{firefox_profile: profile})
# chrome
Hound.start_session(%{
browserName: "chrome",
chromeOptions: %{"args" => ["--user-agent=#{ua}"]}
})
# phantomjs
Hound.start_session(%{
:browserName => "phantomjs",
"phantomjs.page.settings.userAgent" => ua
})
However, if we use it to add metadata, I think that having a common interface
to set this will be required.
I was thinking that being able to pass a hound
key in desired capabilities
could be a clean way to do this, as it is obvious that we are doing something
hound specific and not driver specific.
Hound.start_session(%{
hound: %{
user_agent: ua,
metadata: %{"some" => "metadata for concurrent tests or anything we like"}
}
})
What do you think?
from hound.
That's great. It would be nice, however, if it was a single option indeed, so we can do:
Hound.start_session(user_agent: "our strings")
In particular, I would keep the options for start_session
all Hound specific and nest the driver options under the :driver
key.
from hound.
@tuvistavie once this is all said and done on the hound side, could you also please investigate integration from the Phoenix.Ecto side too? Thank you!
from hound.
/cc @tokafish
from hound.
In particular, I would keep the options for start_session all Hound specific and nest the driver options under the :driver key.
This does seem cleaner, thank you for the feedback!
@HashNuke What do you think?
@tuvistavie once this is all said and done on the hound side, could you also please investigate integration from the Phoenix.Ecto side too? Thank you!
Sure, as soon as I have the time!
from hound.
@tuvistavie I vote for the driver options being under a key too. That way Hound options are easily identifiable.
from hound.
I think we are done here 🎉
from hound.
Related Issues (20)
- Fix broken source links from hexdocs HOT 1
- Hound + Selenium/Firefox does not work with `find_element` HOT 3
- set_cookie error with ChromeDriver
- release a new version? is this package still maintained? HOT 2
- Can "other element would receive the click" become an error?
- (RuntimeError) invalid session id when running on alpine HOT 9
- Change driver in start_session
- Problem with acceptance test in hound not starting server on port 4001 in phoenix HOT 2
- Could not transform value %{"element-6066-11e4-a52e-4f735466cecf" => "d2c5deba-fdff-48db-b319-694aa6542c81"} to element HOT 2
- Support w3c for latest chrome / chromedriver releases HOT 2
- Using hound on Heroku HOT 2
- Incomplete list of keys in the documentation of set_keys
- 1.1.0 3be56f4 mismatch between github and hex HOT 5
- Should all retries load from :retries configuration value? HOT 1
- chromedriver can't start automatically HOT 2
- Improvement: the retry argument of find_element
- fill_field(email, "[email protected]")) transforms `@` into `_`
- Headless Chrome sessions not starting on recent Chrome versions HOT 6
- (Protocol.UndefinedError) protocol String.Chars not implemented for {...} of type Tuple.
- Selenium 4.0 breaking change in URL
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hound.