Open andrewvy opened 7 years ago
Here's another one I came up with, opening chrome and adding a script to evaluate on new pages (took me a while to figure it out):
def open_chrome(css) do
task = Task.async(fn ->
System.cmd(Paths.chromium_executable_path, Constants.chrome_startup_args())
end)
server = ChromeRemoteInterface.Session.new()
{:ok, pages} = ChromeRemoteInterface.Session.list_pages(server)
pages
|> Enum.each(fn(page) ->
{:ok, page_pid} = ChromeRemoteInterface.PageSession.start_link(page)
Page.enable(page_pid)
script = script(css)
Page.addScriptToEvaluateOnNewDocument(page_pid, %{source: script})
end)
{task, server}
end
def script(css_text) do
"""
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '#{css_text}'
var script = document.createElement('script');
script.type = 'text/javascript'
script.src = 'http://localhost:4001/assets/annotations.js'
document.addEventListener('DOMContentLoaded', () => {
var head = document.getElementsByTagName('head')[0]
head.appendChild(style);
head.appendChild(script);
}, false);
"""
end
Here's an example of using evaluate to fetch a remote object and using callfunctionon to operate on the object:
def get_remote_object("css", selector, page_pid) do
case Runtime.evaluate(page_pid, %{expression: "document.querySelector('#{selector}');"}) do
{:ok, %{"result" => %{"result" => %{"subtype" => "null", "type" => "object", "value" => nil}}}} ->
{:warning, "Element Not Found in Browser"}
{:ok, %{"result" => %{"result" => remote_object}}} -> {:ok, cast_remote_object(remote_object)}
end
end
def get_remote_object("xpath", selector, page_pid) do
opts = %{
includeCommandLineAPI: true,
expression: "elements = $x('#{selector}'); elements[0];"
}
case Runtime.evaluate(page_pid, opts) do
{:ok, %{"result" => %{"result" => %{"type" => "undefined"}}}} -> {:warning, "Element Not Found"}
{:ok, %{"result" => %{"result" => remote_object}}} -> {:ok, cast_remote_object(remote_object)}
end
end
def cast_remote_object(%{
"className" => class_name,
"description" => description,
"objectId" => object_id,
"subtype" => subtype,
"type" => type
}) do
%{
class_name: class_name,
description: description,
object_id: object_id,
subtype: subtype,
type: type
}
end
def execute_command({:fill_field, %{strategy: strategy, selector: selector, text: text}}, page_pid) do
with {:ok, remote_object} <-
Utilities.get_remote_object(strategy, selector, page_pid),
{:ok, %{"result" => _focus_result}} <-
DOM.focus(page_pid, %{objectId: remote_object.object_id}),
:ok <- type_text(page_pid, text),
{:ok, %{"result" => result}} <-
Runtime.callFunctionOn(page_pid, %{
arguments: [%{objectId: remote_object.object_id}],
functionDeclaration: "(element) => {element.blur()}",
objectId: remote_object.object_id
})
do
{:ok, result}
else
{:error, error_object} -> cast_error(error_object)
{:warning, message} -> {:warning, message}
end
end
Should benefit by providing some common use-case examples.
These examples are built on unstable version and is not guaranteed to be working in the near future!