Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API v1.0 review #1348

Closed
pavelfeldman opened this issue Mar 11, 2020 · 9 comments
Closed

API v1.0 review #1348

pavelfeldman opened this issue Mar 11, 2020 · 9 comments

Comments

@pavelfeldman
Copy link
Member

pavelfeldman commented Mar 11, 2020

Playwright ✅

  • playwright.chromium
  • playwright.devices
  • playwright.errors
  • playwright.firefox
  • playwright.selectors
  • playwright.webkit
  • Playwright module

Browser ✅

  • event: 'disconnected'
  • browser.close()
  • browser.contexts()
  • browser.isConnected()
  • browser.newContext([options])
  • browser.newPage([options])

BrowserContext ✅

  • event: 'close'
  • event: 'page'
  • browserContext.addInitScript(script[, arg])
  • browserContext.clearCookies()
  • browserContext.clearPermissions()
  • browserContext.close()
  • browserContext.cookies([urls])
  • browserContext.exposeFunction(name, playwrightFunction)
  • browserContext.newPage()
  • browserContext.pages()
  • browserContext.route(url, handler)
  • browserContext.addCookies(cookies)
  • browserContext.setDefaultNavigationTimeout(timeout)
  • browserContext.setDefaultTimeout(timeout)
  • browserContext.setExtraHTTPHeaders(headers)
  • browserContext.setGeolocation(geolocation)
  • browserContext.setHTTPCredentials(httpCredentials)
  • browserContext.setOffline(offline)
  • browserContext.grantPermissions(permissions[], options)
  • browserContext.waitForEvent(event[, optionsOrPredicate])

BrowserType ✅

  • browserType.connect(options)
  • browserType.downloadBrowserIfNeeded([progress])
  • browserType.executablePath()
  • browserType.launch([options])
  • browserType.launchPersistentContext(userDataDir, [options])
  • browserType.launchServer([options])
  • browserType.name()

BrowserServer ✅

  • event: 'close'
  • browserServer.close()
  • browserServer.kill()
  • browserServer.process()
  • browserServer.wsEndpoint()

Worker ✅

  • event: 'close'
  • worker.evaluate(pageFunction[, arg])
  • worker.evaluateHandle(pageFunction[, arg])
  • worker.url()

A11Y ✅

  • accessibility.snapshot([options])

Selectors

  • selectors.register(name, script)

Response ✅

  • response.body()
  • response.finished()
  • response.frame()
  • response.headers()
  • response.json()
  • response.ok()
  • response.request()
  • response.status()
  • response.statusText()
  • response.text()
  • response.url()

Request ✅

  • request.abort([errorCode])
  • request.continue([overrides])
  • request.failure()
  • request.frame()
  • request.fulfill(response)
  • request.headers()
  • request.isNavigationRequest()
  • request.method()
  • request.postData()
  • request.redirectedFrom()
  • request.redirectedTo()
  • request.resourceType()
  • request.response()
  • request.url()

Mouse ✅

  • mouse.click(x, y[, options])
  • mouse.dblclick(x, y[, options])
  • mouse.down([options])
  • mouse.move(x, y[, options])
  • mouse.up([options])

Keyboard ✅

  • keyboard.down(key[, options])
  • keyboard.press(key[, options])
  • keyboard.insertText(text)
  • keyboard.type(text[, options])
  • keyboard.up(key)

Dialog ✅

  • dialog.accept([promptText])
  • dialog.defaultValue()
  • dialog.dismiss()
  • dialog.message()
  • dialog.type()

ConsoleMessage ✅

  • consoleMessage.args()
  • consoleMessage.location()
  • consoleMessage.text()
  • consoleMessage.type()

JSHandle ✅

  • jsHandle.asElement()
  • jsHandle.dispose()
  • jsHandle.evaluate(pageFunction[, arg])
  • jsHandle.evaluateHandle(pageFunction[, arg])
  • jsHandle.getProperties()
  • jsHandle.getProperty(propertyName)
  • jsHandle.jsonValue()

ElementHandle ✅

  • elementHandle.$(selector)
  • elementHandle.$$(selector)
  • elementHandle.$$eval(selector, pageFunction[, arg])
  • elementHandle.$eval(selector, pageFunction[, arg])
  • elementHandle.boundingBox()
  • elementHandle.check([options])
  • elementHandle.click([options])
  • elementHandle.contentFrame()
  • elementHandle.dblclick([options])
  • elementHandle.fill(value[, options])
  • elementHandle.focus()
  • elementHandle.hover([options])
  • elementHandle.ownerFrame()
  • elementHandle.press(key[, options])
  • elementHandle.screenshot([options])
  • elementHandle.scrollIntoViewIfNeeded()
  • elementHandle.selectOption(values[, options])
  • elementHandle.setInputFiles(files)
  • elementHandle.toString()
  • elementHandle.type(text[, options])
  • elementHandle.uncheck([options])

Frame ✅

  • frame.$(selector)
  • frame.$$(selector)
  • frame.$$eval(selector, pageFunction[, arg])
  • frame.$eval(selector, pageFunction[, arg])
  • frame.addScriptTag(options)
  • frame.addStyleTag(options)
  • frame.check(selector, [options])
  • frame.childFrames()
  • frame.click(selector[, options])
  • frame.content()
  • frame.dblclick(selector[, options])
  • frame.evaluate(pageFunction[, arg])
  • frame.evaluateHandle(pageFunction[, arg])
  • frame.fill(selector, value[, options])
  • frame.focus(selector[, options])
  • frame.frameElement()
  • frame.goto(url[, options])
  • frame.hover(selector[, options])
  • frame.isDetached()
  • frame.name()
  • frame.parentFrame()
  • frame.press(selector, key[, options])
  • frame.selectOption(selector, values[, options])
  • frame.setContent(html[, options])
  • frame.title()
  • frame.type(selector, text[, options])
  • frame.uncheck(selector, [options])
  • frame.url()
  • frame.waitFor(selectorOrFunctionOrTimeout[, options[, arg]])
  • frame.waitForFunction(pageFunction[, options[, arg]])
  • frame.waitForLoadState([options])
  • frame.waitForNavigation([options])
  • frame.waitForSelector(selector[, options])

Page ✅

  • event: 'close'
  • event: 'console'
  • event: 'dialog'
  • event: 'domcontentloaded'
  • event: 'filechooser'
  • event: 'frameattached'
  • event: 'framedetached'
  • event: 'framenavigated'
  • event: 'load'
  • event: 'pageerror'
  • event: 'popup'
  • event: 'request'
  • event: 'requestfailed'
  • event: 'requestfinished'
  • event: 'response'
  • event: 'worker'
  • page.$(selector)
  • page.$$(selector)
  • page.$$eval(selector, pageFunction[, arg])
  • page.$eval(selector, pageFunction[, arg])
  • page.accessibility
  • page.addInitScript(script[, arg])
  • page.addScriptTag(options)
  • page.addStyleTag(options)
  • page.check(selector, [options])
  • page.click(selector[, options])
  • page.close([options])
  • page.content()
  • page.context()
  • page.coverage
  • page.dblclick(selector[, options])
  • page.emulateMedia(options)
  • page.evaluate(pageFunction[, arg])
  • page.evaluateHandle(pageFunction[, arg])
  • page.exposeFunction(name, playwrightFunction)
  • page.fill(selector, value[, options])
  • page.focus(selector[, options])
  • page.frame(options)
  • page.frames()
  • page.goBack([options])
  • page.goForward([options])
  • page.goto(url[, options])
  • page.hover(selector[, options])
  • page.isClosed()
  • page.keyboard
  • page.mainFrame()
  • page.mouse
  • page.opener()
  • page.pdf([options])
  • page.press(selector, key[, options])
  • page.reload([options])
  • page.route(url, handler)
  • page.screenshot([options])
  • page.selectOption(selector, values[, options])
  • page.setContent(html[, options])
  • page.setDefaultNavigationTimeout(timeout)
  • page.setDefaultTimeout(timeout)
  • page.setExtraHTTPHeaders(headers)
  • page.setViewportSize(viewportSize)
  • page.title()
  • page.type(selector, text[, options])
  • page.uncheck(selector, [options])
  • page.url()
  • page.viewportSize()
  • page.waitFor(selectorOrFunctionOrTimeout[, options[, arg]])
  • page.waitForEvent(event[, optionsOrPredicate])
  • page.waitForFunction(pageFunction[, options[, arg]])
  • page.waitForLoadState([options])
  • page.waitForNavigation([options])
  • page.waitForRequest(urlOrPredicate[, options])
  • page.waitForResponse(urlOrPredicate[, options])
  • page.waitForSelector(selector[, options])
  • page.workers()

CDPSession ✅

  • cdpSession.detach()
  • cdpSession.send(method[, params])

ChromiumCoverage ✅

  • chromiumCoverage.startCSSCoverage([options])
  • chromiumCoverage.startJSCoverage([options])
  • chromiumCoverage.stopCSSCoverage()
  • chromiumCoverage.stopJSCoverage()

ChromiumBrowserContext✅

  • event: 'backgroundpage'
  • event: 'serviceworker'
  • chromiumBrowserContext.backgroundPages()
  • chromiumBrowserContext.serviceWorkers()
  • chromiumBrowserContext.newCDPSession(page)

ChromiumBrowser ✅

  • chromiumBrowser.newBrowserCDPSession()
  • chromiumBrowser.startTracing([page, options])
  • chromiumBrowser.stopTracing()
@JoelEinbinder
Copy link
Contributor

JoelEinbinder commented Mar 12, 2020

browserContext.setDefaultNavigationTimeout, browserContext.setDefaultTimeout will change to browserContext.setDefaultTimeouts({ navigation, click, type })
Rationale: There are numerous delays for clicks and types and what not, would be nice to configure in a generic manner

Joel:
Sure there are different places delays are used, but what about each thing let’s me decide what the delay should be? Trying to tune individual timeouts seems like an “always wrong” strategy to me.

Pavel:
We've seen requests for tuning delays while typing, pressing and clicking. We also have unclear semantics for the click today that waits for selector for the timeoutms and then waits for navigation for navtimeoutms. Let's for now agree that present default timeout setters are broken.

Yury:
If we leave the default options let's remove the setters and only allow passing them in the context constructor. For fine grain control many methods already accept custom timeouts, changing defaults on the flight seems weird.

@JoelEinbinder
Copy link
Contributor

JoelEinbinder commented Mar 12, 2020

browserContext.waitForEvent(event[, optionsOrPredicate])

Joel
This looks like we are fighting the node standard library. The old waitForTarget made sense because it included existing targets. If waitForEvent doesn’t do that, I’d rather just remove it. Why don’t we have it on workers?

Pavel
Luckily there is no support for parametrized events we would need to fight.

@JoelEinbinder
Copy link
Contributor

browserType.downloadBrowserIfNeeded([progress])

Due to yarn, I believe this needs to take a download folder. @aslushnikov should remember the details.

@JoelEinbinder
Copy link
Contributor

browserType.errors

Let’s remove the shortcuts to errors on the browserTypes. We aren’t saving anyone anything in practice. TypeScript users need to import playwright for types already. I think other users are more likely to get passed a browser/context than a browser type. It feels out of place.

@JoelEinbinder
Copy link
Contributor

JoelEinbinder commented Mar 12, 2020

Joel

browserServer.close()
browserServer.kill()

When do I choose kill? Maybe we know based on how the server was launched (persistent)? If kill isn’t recommended, maybe we can let people do it through the process if they need to.

Dmitry

browserServer.kill() does a bit of windows-specific handling which is convenient. I'd rather let it be and clarify the docs.

@JoelEinbinder
Copy link
Contributor

s/sendCharacters/insertText

@aslushnikov
Copy link
Collaborator

aslushnikov commented Mar 13, 2020

When do I choose kill? Maybe we know based on how the server was launched (persistent)?

@JoelEinbinder browser.kill() is sync and can be called from sync event handlers, e.g. process.on('SIGTERM') handler. These are handy for embedding testrunners.

If kill isn’t recommended, maybe we can let people do it through the process if they need to.

@JoelEinbinder killing is involved across OS'es (e.g. on win we use taskkill).

@JoelEinbinder
Copy link
Contributor

When do I choose kill? Maybe we know based on how the server was launched (persistent)? If kill isn’t recommended, maybe we can let people do it through the process if they need to.

@JoelEinbinder killing is involved across OS'es (e.g. on win we use taskkill). Also, killing can be called from sync event handlers, e.g. process.on('SIGTERM') handler. These are probably handy for embedding testrunners.

So if I am in SIGTERM I call kill, otherwise I call close? If I’m in sigterm and I don’t do anything, will we leak processes?

@aslushnikov
Copy link
Collaborator

So if I am in SIGTERM I call kill, otherwise I call close?

@JoelEinbinder the comparison table between the two:

  • browser.kill() is a process kiling. PROs: it's fast & sync. CONs: doesn't guarantee to save any browser data and might generate a crashdump if your OS is configured to do so.
  • browser.close() is a graceful shutdown. PROs: saves your browser data and doesn't generate crashdump. CONs: slow & non-sync.

If I’m in sigterm and I don’t do anything, will we leak processes?

By default, PW handles SIGINT/SIGTERM/SIGHUP and closes browser appropriately. This behavior is configurable with launch flags.

If parent node.js process terminates, Playwright will kill the launched browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants