Playwright-compatible API built on WebDriver BiDi
Dependencies
moon add mizchi/playwrightimport "mizchi/playwright" as @pw
import "mizchi/playwright/test" as @pwt
let chromium = @pw.chromium()
let _ = @pwt.expect(chromium.name()).to_equal("chromium")
async test "dsl helpers" {
@pwt.configure_test(
retry_times=3,
timeout_ms=3_000,
expect_timeout_ms=800,
expect_interval_ms=10,
shard_index=1,
shard_total=2,
)
let _ = @pwt.step("open", fn() -> Int { 1 })
// shard は設定値を省略可能
@pwt.shard(item_index=0, item_total=2, fn() {})
// retry / timeout は設定値をデフォルトとして使える
let _ = @pwt.retry(async fn() -> Int { 1 })
let _ = @pwt.timeout(async fn() -> Int { 1 })
// 一定時間リトライしながら assertion
@pwt.to_pass(async fn() {
@pwt.expect("ok").to_equal("ok")
})
// expect.poll 相当
@pwt.expect_poll(async fn() -> String { "done-1" }).to_match("done-\\d+")
}// test/integration/global.setup.js
const { chromium } = require("@playwright/test")
const fs = require("node:fs/promises")
const path = require("node:path")
module.exports = async () => {
const server = await chromium.launchServer({ headless: true })
const runtimeDir = path.join(__dirname, ".runtime")
await fs.mkdir(runtimeDir, { recursive: true })
await fs.writeFile(
path.join(runtimeDir, "state.json"),
JSON.stringify({ ws_endpoint: server.wsEndpoint() }),
"utf-8",
)
return async () => {
await server.close()
}
}// test/integration/config_bridge.spec.js (抜粋)
const state = JSON.parse(fs.readFileSync(".runtime/state.json", "utf-8"))
const wsEndpoint = state.ws_endpoint
spawnSync("moon", [
"run",
"src/playwright/test_utils/integration_bridge",
"--target",
"js",
/* retry/timeout/shard など */,
wsEndpoint,
])pub suberror PlaywrightError {
StrictModeViolation(String, Int)
}pub struct BoundingBox {
x : Double
y : Double
width : Double
height : Double
}impl Eq for BoundingBoximpl Show for BoundingBoxpub struct Browser {
// private fields
}async fn Browser::new_context(self : Browser, viewport? : (Int, Int), user_agent? : String, locale? : String, timezone_id? : String, geolocation? : (Double, Double), permissions? : Array[String], color_scheme? : String, reduced_motion? : String, forced_colors? : String, accept_downloads? : Bool, ignore_https_errors? : Bool, javascript_enabled? : Bool, bypass_csp? : Bool, offline? : Bool, device_scale_factor? : Double, is_mobile? : Bool, has_touch? : Bool) -> BrowserContextasync fn Browser::new_page(self : Browser, viewport? : (Int, Int), user_agent? : String, locale? : String, timezone_id? : String, ignore_https_errors? : Bool, javascript_enabled? : Bool, bypass_csp? : Bool, offline? : Bool, color_scheme? : String, device_scale_factor? : Double, is_mobile? : Bool, has_touch? : Bool) -> Pagepub struct BrowserContext {
// private fields
}fn BrowserContext::close_with_error_callback(self : BrowserContext, on_error : (Error) -> Unit) -> Unitasync fn BrowserContext::grant_permissions(self : BrowserContext, permissions : Array[String], origin? : String) -> Unitasync fn BrowserContext::set_geolocation(self : BrowserContext, latitude : Double, longitude : Double, accuracy? : Double) -> Unitpub enum BrowserKind {
Chromium
Firefox
WebKit
}impl Show for BrowserTypeasync fn BrowserType::launch(self : BrowserType, headless? : Bool, args? : Array[String], channel? : String, chromium_sandbox? : Bool, devtools? : Bool, downloads_path? : String, executable_path? : String, handle_sighup? : Bool, handle_sigint? : Bool, handle_sigterm? : Bool, slow_mo? : Int, timeout? : Int) -> Browserasync fn BrowserType::launch_persistent_context(self : BrowserType, user_data_dir : String, headless? : Bool, args? : Array[String], channel? : String, slow_mo? : Int, timeout? : Int) -> BrowserContextpub struct Clip {
x : Double
y : Double
width : Double
height : Double
}pub(all) struct ConsoleMessage {
level : String
text : String
source : String
}pub struct Cookie {
name : String
value : String
url : String?
domain : String?
path : String?
expires : Double?
http_only : Bool?
secure : Bool?
same_site : String?
}pub struct ElementHandle {
// private fields
}async fn ElementHandle::evaluate_handle(self : ElementHandle, page_function : String, arg? : Json) -> JSHandlepub struct Expect[T] {
actual : T
}#callsite(autofill(loc))
async fn Expect::to_have_class(self : Expect[Locator], expected : String, expected_tokens? : Array[String], expected_list? : Array[String], expected_list_tokens? : Array[Array[String]], timeout? : Int, msg? : String, match_mode? : String, normalize? : Bool, loc~ : SourceLoc) -> Unit#callsite(autofill(loc))
async fn Expect::to_have_css(self : Expect[Locator], name : String, expected : String, timeout? : Int, msg? : String, match_mode? : String, normalize? : Bool, numeric? : Bool, tolerance? : Double, relative? : Bool, root_font_size? : Double, em_size? : Double, percent_base? : Double, viewport_width? : Double, viewport_height? : Double, loc~ : SourceLoc) -> Unitpub struct Frame {
url_ : String
name_ : String
}pub struct JSHandle {
// private fields
}pub enum Length {
Points(Double)
Css(String)
}pub struct Locator {
// private fields
}async fn Locator::screenshot(self : Locator, path? : String, type_? : String, quality? : Int, omit_background? : Bool, timeout? : Int, scale? : String) -> ResponseBodyasync fn Locator::select_option(self : Locator, values : Array[SelectOption], force? : Bool, no_wait_after? : Bool, timeout? : Int) -> Array[String]impl Show for NetworkEventpub struct Page {
// private fields
}async fn Page::pdf(self : Page, path? : String, scale? : Double, display_header_footer? : Bool, header_template? : String, footer_template? : String, print_background? : Bool, landscape? : Bool, page_ranges? : String, format? : String, width? : String, height? : String, margin? : Margin, prefer_css_page_size? : Bool) -> ResponseBodyasync fn Page::screenshot(self : Page, path? : String, type_? : String, quality? : Int, full_page? : Bool, clip? : Clip, omit_background? : Bool, timeout? : Int, scale? : String) -> ResponseBodyasync fn Page::select_option(self : Page, selector : String, values : Array[SelectOption], force? : Bool, no_wait_after? : Bool, timeout? : Int) -> Array[String]async fn Page::wait_for_selector(self : Page, selector : String, state? : String, timeout? : Int, strict? : Bool) -> ElementHandle?pub struct Response {
url_ : String
status_ : Int
status_text_ : String
headers_ : Headers
from_cache_ : Bool
from_service_worker_ : Bool
}pub struct SelectOption {
value : String?
label : String?
index : Int?
}impl Eq for SelectOptionimpl Show for SelectOptionPlaywright-compatible API built on WebDriver BiDi
Dependencies