Skip to content

Commit bbbef41

Browse files
committed
API: impl BrowserContext.set_geolocation
Warning: this function has not yet been successfully tested. > So far, the test runs have failed to receive location data and instead > experiences "error code 2", which [reportedly](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError/code) > represents `POSITION_UNAVAILABLE` - "The acquisition of the geolocation > failed because one or several internal sources of position returned an internal error."
1 parent cb3881d commit bbbef41

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

.envrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export REPO="$(expand_path .)"
55
export ERL_AFLAGS="-kernel shell_history enabled" # persistent iex history
66

77
# default: true
8-
export PLAYWRIGHT_HEADLESS=false
8+
# export PLAYWRIGHT_HEADLESS=false
99

1010
# default transport: driver (websocket is the one alternative)
1111
# export PLAYWRIGHT_TRANSPORT=websocket

lib/playwright/browser_context.ex

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,62 @@ defmodule Playwright.BrowserContext do
10301030
Channel.post({context, "setExtraHTTPHeaders"}, %{headers: serialize_headers(headers)})
10311031
end
10321032

1033+
@doc """
1034+
Sets the context's geolocation.
1035+
1036+
Passing `nil` emulates position unavailable.
1037+
1038+
> #### NOTE {: .info}
1039+
>
1040+
> Consider using `Playwright.BrowserContext.grant_permissions/3` to grant
1041+
> permissions for the browser context pages to read geolocation.
1042+
1043+
> #### WARNING! {: .warning}
1044+
>
1045+
> As of 2024-10-09, this function has not yet been successfully tested.
1046+
> So far, the test runs have failed to receive location data and instead
1047+
> experiences "error code 2", which [reportedly](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError/code)
1048+
> represents `POSITION_UNAVAILABLE` - "The acquisition of the geolocation
1049+
> failed because one or several internal sources of position returned an internal error."
1050+
1051+
## Usage
1052+
1053+
BrowserContext.set_geolocation(context, %{
1054+
latitude: 59.95,
1055+
longitude: 30.31667
1056+
})
1057+
1058+
## Arguments
1059+
1060+
| name | | description |
1061+
| ------------- | ---------- | ------------------------------- |
1062+
| `context` | | The "subject" `BrowserContext`. |
1063+
| `geolocation` | | `BrowserContext.geolocation()`. |
1064+
1065+
### Geolocation settings
1066+
1067+
| name | | description |
1068+
| ----------- | ---------- | ----------------------------------- |
1069+
| `latitude` | | Latitude between `-90` and `90`. |
1070+
| `lingitude` | | Longitude between `-180` and `180`. |
1071+
| `accuracy` | (optional) | Non-negative accuracy value. Defaults to `0`. |
1072+
1073+
## Returns
1074+
1075+
- `BrowserContext.t()`
1076+
- `{:error, Error. t()}`
1077+
"""
1078+
@pipe {:set_geolocation, [:context, :geolocation]}
1079+
@spec set_geolocation(t(), geolocation() | nil) :: t() | {:error, Error.t()}
1080+
def set_geolocation(context, params \\ nil)
1081+
1082+
def set_geolocation(%BrowserContext{} = context, params) when is_map(params) do
1083+
Channel.post({context, :set_geolocation}, params)
1084+
end
1085+
1086+
def set_geolocation(%BrowserContext{} = context, nil) do
1087+
Channel.post({context, :set_geolocation})
1088+
end
10331089

10341090
@spec set_offline(t(), boolean()) :: t() | {:error, Error.t()}
10351091
def set_offline(%BrowserContext{} = context, offline) do

test/api/browser_context_test.exs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,57 @@ defmodule Playwright.BrowserContextTest do
936936
end
937937
end
938938

939+
# skip: See documentation comment for `BrowserContext.set_geolocation/2`
940+
@tag :skip
941+
describe "BrowserContext.set_geolocation/2" do
942+
test "on success, returns the 'subject' `BrowserContext`", %{page: page} do
943+
context = Page.context(page)
944+
assert %BrowserContext{} = BrowserContext.set_geolocation(context, nil)
945+
end
946+
947+
test "on failure, returns `{:error, error}`", %{page: page} do
948+
context = Page.context(page)
949+
context = %{context | guid: "bogus"}
950+
951+
assert {:error, %Error{message: "Target page, context or browser has been closed"}} =
952+
BrowserContext.set_geolocation(context, %{})
953+
end
954+
955+
test "...", %{assets: assets, page: page} do
956+
context = Page.context(page)
957+
BrowserContext.grant_permissions(context, ["geolocation"])
958+
959+
BrowserContext.set_geolocation(context, %{latitude: 10, longitude: 10})
960+
961+
Page.goto(page, assets.empty)
962+
963+
geolocation =
964+
Page.evaluate(page, """
965+
async() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {
966+
resolve({latitude: position.coords.latitude, longitude: position.coords.longitude});
967+
}))
968+
""")
969+
|> IO.inspect(label: "geolocation")
970+
971+
assert %{latitude: 10, longitude: 10} = geolocation
972+
end
973+
end
974+
975+
describe "BrowserContext.set_geolocation!/2" do
976+
test "on success, returns the 'subject' `BrowserContext`", %{page: page} do
977+
context = Page.context(page)
978+
assert %BrowserContext{} = BrowserContext.set_geolocation!(context, %{latitude: 0, longitude: 0})
979+
end
980+
981+
test "on failure, raises `RuntimeError`", %{page: page} do
982+
assert_raise RuntimeError, "Target page, context or browser has been closed", fn ->
983+
context = Page.context(page)
984+
context = %{context | guid: "bogus"}
985+
BrowserContext.set_geolocation!(context, %{latitude: 0, longitude: 0})
986+
end
987+
end
988+
end
989+
939990
describe "BrowserContext.set_offline/2" do
940991
test "returns 'subject'", %{page: page} do
941992
context = Page.context(page)

0 commit comments

Comments
 (0)