Releases: grafana/xk6-browser
v0.8.1
This is a patch release that fixes a few bugs, including one regression bug introduced in v0.8.0, adds one improvement on documentation, and does minor internal modifications.
Bugs fixed
- Fix mapping of
Page
'sKeyboard
,Mouse
, andTouchscreen
properties. (#751) - Fix
Page.URL()
method. (#758) - Fix
Frame.Title()
method. (#761)
Improvements
- Added contributing guidelines. (#750)
Internals
v0.8.0
xk6-browser v0.8.0 is here! 🎉
This release contains preparation for the upcoming xk6-browser
and k6
merge, preparations for the upcoming Async API features, bug fixes, and code refactoring.
Experimental Module Merge into k6
We've been busy preparing for this big change that will occur very soon 🤞. We have refactored the code in preparation for the merge into k6
(see the related issue list). This will mean that all future releases of xk6-browser
will also be part of the k6
releases (as an experimental module). Merging xk6-browser
into k6
will allow you to run both the protocol and browser tests using the same k6
command line tool. This will also increase the reach and visibility of xk6-browser
and allow us to collect more feedback and guidance from the community to tailor our product to your needs. It's worth noting that we're not merging the two code bases into a single one. xk6-browser
will still be in its own repository.
As an experimental module, some of our APIs are likely to change, causing breaking changes in future releases—for example, now that we have async
/await
keyword support, we're going to move most of our APIs to async
. Changes in APIs also means that your Playwright scripts will also start to work in xk6-browser
with less and less tweaking of your xk6-browser
test scripts in the upcoming releases—As per our rough compatibility goal with Playwright APIs.
Currently, browser based tests can only be performed within your own test environments, and it won't be available in the cloud (yet). Keep your eyes peeled though on future releases, and the blog to hear more on the public launch of browser testing in the cloud.
With this release we are continuing to build and upload the artifacts (binaries) for you to download and work with. In the near future we intend to stop that, and instead we will redirect you to the k6 repo, where you will be able to download the latest binary with browser test functionality. We may also stop releasing the release notes here and move them to the k6 release notes. We will create a blog post outlining these details soon.
Improvements
-
Convert promisified (
.then()
) examples toasync
/await
. #703Now all our examples use
async
/await
instead of the promise.then()
chains. Please look at theexamples/
folder to see how we use the new feature. We're changing the meaning of this folder and will use it for internal JavaScript tests instead of showing how to use thexk6-browser
extension. -
Log a friendly message if the browser process closes before
xk6-browser
is able to connect to the browser. #735
Documentation
- We're updating all our docs so that they reflect the merge and the
async
/await
changes. These updates will be released after the merge and the latest version ofk6
has been released.
Internal bug fixes and improvements
-
Pre-merge: Map k6-browser Async API to Goja. #683
This is the groundwork for abstracting our internals to get ready for the merge and make it straightforward to upgrade our API to async in the upcoming releases. With this work, we're now able to unlock the following features:
- Provide an easy switch to the k6 browser Async API.
- Unlock merging of k6 browser to k6 core: Mapping Async APIs.
- Increase developer productivity by clearly separating the k6 browser code and Goja.
-
Fix the race condition in frame management. #696
-
Fix dismiss dialog test bug. #713
-
Fix frame manager navigate frame bug. #714
-
Fix lifecycle tests bug. #712
-
Several other refactors and bug fixes to improve maintainability and stability: (#694, #699, #700, #723, #716, #734, #740, #741).
v0.7.0
xk6-browser v0.7.0 is here! 🎉
We've been busy preparing for big changes in the future, so this minor release is smaller than usual. It contains a new feature to unblock users using dialog
boxes, a fix, and internal improvements.
Experimental Module Merge into k6
We're excited to reveal that in an upcoming future release of k6
you will be able to run browser tests -- we're merging xk6-browser
into k6
. The merge will expose the browser tests via an experimental module importable with k6/experimental/browser
, so expect a small breaking change there. We now have a solid foundation, and to help us shape it into a better tool we need more people to use it; this is why we're doing the merge. It's worth noting that we're not merging the two code bases into a single one.
This might mean we will eventually stop releasing new versions of xk6-browser
binaries, and instead point people to the latest release of k6
. When it comes to building xk6-browser
from source, that won't change, so you will still be able to build from source the same way you have been doing so already.
Bugs fixed
xk6-browser
no longer panics when it navigates to a website that containsiframes
which themselves navigate to a different origin to the mainframe
(e.g. a website containing an embedded Youtube video). (#677)
New features
xk6-browser
will now automatically dismiss dialog boxes (alert
,confirm
,prompt
, andbeforeunload
). (#663)
Improvements
-
Improved launching of a browser without providing any options. (#649)
We couldn't launch a new browser without providing an empty object. We've fixed this, so now you can launch a new browser without an empty object.
With the empty object:
const browser = chromium.launch({});
Without the empty object:
const browser = chromium.launch();
Documentation
-
Updated the demo video on our README. (#639)
Now it shows the usage for xk6-browser version v0.6.0 and above.
-
Simplified the README. (#656)
You can now find the documentation here.
-
Updated the project roadmap. (#658)
Internals
-
Upgraded
k6
dependency tov0.42.0
. (#?) -
Refactored the lifecycle events code. (#647, #644)
This shouldn't change any existing behavior, but if you notice anything that doesn't work as expected, please let us know.
-
Cleanup unused dependencies. (#674)
Experimental Module Merge into k6
Here are some internal changes that will help us achieve the merge goal in the near future (we still have some more work to do before we can do the merge):
v0.6.0
xk6-browser v0.6.0 is here! 🎉
This minor release contains essential stability fixes, bug fixes that we found while stress testing the application, improvements, and a continuation of our efforts to migrate to async APIs.
Bugs fixed
-
Fixed
ignoreDefaultArgs
. (#547)We're now not hiding scrollbars while running in headless mode. This issue was causing the browser viewport width to be larger than it should be.
-
Fixed data race while logging. (#531)
-
Fixed sending metrics with incorrect timestamp to the Cloud. (#551)
The issue was preventing users from analyzing performance metrics in the Cloud.
-
Fixed the
waitUntil
option forPage.goto
,Page.reload
andPage.waitForLoadState
. (#578, #623, #628)This now works as expected with the
load
,domcontentloaded
andnetworkidle
lifecycle events.networkidle
might not work so well with websites that are very chatty and so the wait eventually could timeout. -
Fixed a possible deadlock that can happen while navigating frames. (#539)
-
Fixed two possible data races which could occur during a navigation. (#630)
Breaking changes
-
Page.goto
is now an asynchronous method that returns aPromise
. (#583, #591)All our examples have been updated to work with async
Page.goto
. For example, you can look at thebrowser_args.js
example for how to use it.Note that the
async
andawait
keywords are not yet supported (see this k6 issue for a workaround), so resolving thePromise
usingthen()
is required for scripts to continue to work correctly. -
Setting a browser launch property to
null
will be ignored and the default will be used; take a look at the BrowserType.launch documentation for the defaults. (#616, #620)For example:
const browser = chromium.launch({ headless: null, // will be set to true logCategoryFilter: null, // will be set to '.*' timeout: null, // will be set to 30s });
-
Setting some browser launch options will be ignored on Cloud. (#627)
Setting the following options will be ignored, and they take their default values as follows:
option default note devtools false executablePath "" will be determined by xk6-browser headless true
Improvements
-
Added an example of how to use
xk6-browser
alongsidek6
. (#529) -
Improved handling of browser process exit and WS connection closing. (#535)
We're now waiting for the browser process to exit before ending the iteration. Previously, we would cancel the browser context prematurely, which caused the process unexpectedly ended and signal: killed errors.
-
Improved the internal event handling mechanism. (#555)
Now we're handling events in the order we receive them. This change has drastically improved the extension's stability.
-
Improved emitting errors from the browser. (#598)
Now we're returning the error that can occur while launching a browser. Previously, we would log a file already closed error if the browser process exits prematurely.
-
Added a Docker example. (#556, #631)
You can now use xk6-browser using Docker. For example:
docker-compose run -T xk6-browser run - <examples/browser_on.js
-
Upgraded the project to be compatible with Go 1.19. (#568)
-
Added a troubleshooting document. (#569)
This document is a good place to start when you have issues installing or running xk6-browser.
-
Added a GitHub issues template. (#584)
It makes it easier for you to send us the details of the problems you're facing.
-
Return an error on invalid
BrowserType.launch
options. (#608) -
Fixed the example test script
browser_args.js
on macOS. (#629)
Internals
v0.5.0
xk6-browser v0.5.0 is here! 🎉
This minor release contains a new feature, a few important stability fixes, some breaking changes, improvements, and a continuation of our efforts to migrate to async APIs. Coinciding with this release, is the up-to-date documentation, which can be found at https://k6.io/docs/javascript-api/xk6-browser/. Only a few of the most used classes like Browser
and BrowserContext
are currently well documented, and we're working hard on updating the rest of the API.
New Feature
-
Combining key presses when inputting text in an input field now works with the
Shift
modifier key (#326, #522).const l = page.locator('#input-text-test'); l.press('Shift+KeyH+i'); // "Hi" l.press('Backspace'); // "H" l.press('Backspace'); // "" l.press('KeyH+i'); // "hi"
Bugs fixed
-
A couple of
Page.goto()
race conditions, where the call would timeout waiting for the navigation event. This was mainly found to occur in CI, but it could happen in real world tests as well.
(#480, #501) -
A
Page.waitForNavigation()
race condition, where the call would fail with a Go nil pointer dereference error. (#500)
Breaking changes
-
chromium
is now an importable object, which changes the syntax for launching tests using Chromium (which is still the only supported browser type). (#462, #515)Previously, scripts called
launch()
on thek6/x/browser
module directly, and specified'chromium'
as the first argument:import launcher from 'k6/x/browser'; export default function () { const browser = launcher.launch('chromium', { headless: false, }); ...
Now,
chromium
must be imported separately andchromium.launch()
should be called instead:import { chromium } from 'k6/x/browser'; export default function () { const browser = chromium.launch({ headless: false, }); ...
The same options are supported in the
chromium.launch()
method as in the previouslaunch()
function. -
ElementHandle.click()
is now an asynchronous method that returns a Promise. (#466)Note that the
async
andawait
keywords are not yet supported (see this k6 issue for a workaround), so resolving the Promise usingthen()
is required for scripts to continue to work correctly.See the
fillform.js
example for how to use it. -
Page.waitForNavigation()
is now an asynchronous method that returns a Promise. (#467)When expecting a navigation triggered by a
click()
, it's important to resolve both Promises inside aPromise.all()
call, to avoid a race condition.See the
fillform.js
example for how to use it. -
As part of the
Page.waitForNavigation()
async change, a timeout error won't interrupt the script iteration anymore, and the Promise will be rejected instead. (#508)This gives more flexibility, as you can handle this error however you prefer, including interrupting the iteration. For example:
import { fail } from 'k6'; export default function () { ... Promise.all([ page.waitForNavigation({ timeout: 1000 }), page.locator('a').click(), ]).then(() => { // Everything went well, the page navigated. }, (err) => { console.log(err); // "waiting for navigation: timed out after 1s" fail(err); // interrupt the iteration });
Improvements
- We've made more changes to our log messages to make them more concise and user friendlier. (#438)
Internals
v0.4.0
xk6-browser v0.4.0 is here! 🎉
In this minor release, we implemented a large portion of a new API that will help you find elements on a page in a more robust way, fixed critical bugs, and made some improvements and code refactoring!
The team is aware that the extension is currently unstable for many users. This stems from the complexity in how CDP events from the browser and from our own internal event-based system are currently handled, as well as our lack of async support in JavaScript APIs, which introduces race conditions and can lead to intermittent failures. We've been delaying tackling these issues since it requires a substantial rearchitecture of core systems, but rest assured, it's currently our top priority and these issues will be addressed by, hopefully, the next release. If you want to follow along the progress, subscribe to issues #427 and #428.
New features
Locator API (#100)
The Locator API makes it easier to work with dynamically changing elements. Some of the benefits of using it over existing ways to locate an element (e.g. Page.$()
) include:
- Helps with writing robust tests by finding an element even if the underlying frame navigates.
- Makes it easier to work with dynamic web pages and SPAs built with Svelte, React, Vue, etc.
- Enables the use of test abstractions like the Page Object Model (POM) pattern to simplify and organize tests. See this example.
We follow Playwright's API and now cover most ElementHandle
methods. 🎉 This is the first version of the Locator API, which paves the way for us to develop additional features on top of it in the upcoming milestones. For example, we can support React or Vue selectors in the future on top of the current version.
Here's an example:
import launcher from "k6/x/browser";
export default function () {
const browser = launcher.launch('chromium', {
headless: false,
});
const context = browser.newContext();
const page = context.newPage();
page.goto("https://test.k6.io/flip_coin.php", {
waitUntil: "networkidle",
});
/*
In this example, we will use two locators, matching a
different betting button on the page. If you were to query
the buttons once and save them as below, you would see an
error after the initial navigation.
const heads = page.$("input[value='Bet on heads!']");
const tails = page.$("input[value='Bet on tails!']");
The Locator API allows you to get a fresh element handle each
time you use one of the locator methods. And, you can carry a
locator across frame navigations. Let's create two locators;
each locates a button on the page.
*/
const heads = page.locator("input[value='Bet on heads!']");
const tails = page.locator("input[value='Bet on tails!']");
const currentBet = page.locator("//p[starts-with(text(),'Your bet: ')]");
// the tails locator clicks on the tails button by using the
// locator's selector.
tails.click();
// Since clicking on each button causes page navigation,
// waitForNavigation is needed. It's because the page
// won't be ready until the navigation completes.
page.waitForNavigation();
console.log(currentBet.innerText());
// the heads locator clicks on the heads button by using the
// locator's selector.
heads.click();
page.waitForNavigation();
console.log(currentBet.innerText());
tails.click();
page.waitForNavigation();
console.log(currentBet.innerText());
page.close();
browser.close();
}
The implemented methods in this release are:
-
page.locator(selector)
(#310)Creates and returns a new page locator given a selector with strict mode on. The strict mode only allows selecting a single matching element, and will throw an error if multiple matches are found.
-
locator.click([options])
(#318) -
locator.dblclick([options])
(#332) -
locator.check([options])
(#362) -
locator.uncheck([options])
(#365) -
locator.isChecked([options])
(#369) -
locator.isEditable([options])
(#372) -
locator.isEnabled([options])
(#373) -
locator.isDisabled([options])
(#375) -
locator.isVisible([options])
(#376) -
locator.isHidden([options])
(#377) -
locator.fill(value, [options])
(#380) -
locator.focus([options])
(#388) -
locator.getAttribute(name, [options])
(#390) -
locator.innerHTML([options])
(#392) -
locator.innerText([options])
(#393) -
locator.textContent([options])
(#394) -
locator.inputValue([options])
(#395) -
locator.selectOption(values, [options])
(#397) -
locator.press(key, [options])
(#398) -
locator.type(text, [options])
(#399) -
locator.hover([options])
(#400) -
locator.tap([options])
(#401) -
locator.dispatchEvent(type, eventInit, [options])
(#405) -
locator.waitFor([options])
(#406)
Bugs fixed
-
Fixed zombie browser processes. (#306)
Before this fix, browser processes remained active even after the test or k6 test runs. This could sometimes saturate the machine and therefore could affect the tests.
-
Fixed cleanup of the browser's temporary directory. (#323, #409)
The temporary directory is now properly removed when
Browser.close()
is called, or when the iteration or test run completes. This will help ensure that any private data that the browser caches in the temporary directory is deleted.NOTE: There is a small chance that the temporary directory will not be cleaned and a ticket has been opened to track the next step/fix. (#403)
-
Fixed keyboard press of modifier keys (e.g.
Shift
) inkeyboard.down
andkeyboard.up
. (#325) -
Fixed
page.content()
so that it no longer panics. (#327) -
Fixed
ElementHandle.fill()
. (#383)Before, it was not filling in the text in the selected input element.
-
Fixed
ElementHandle.tap()
. (#401)Before, it was performing the tap without respecting the vertical coordinate.
-
Fixed timeout detection. (#411)
Before this fix, we couldn't detect the timeouts properly. For example if we write a test where we are retrieving the contents of an element that doesn't exist, it used to return an empty string, but now it will raise a timeout error correctly. The current system is still unstable because this fix re-surfaced a data race bug that happens from time to time (happens on frame navigation). Previously reported in #254
-
Fixed a premature crash due to occasional incorrect type conversions. (#425)
This is still an issue caused by internal race conditions (#427), but the extension no longer crashes because of incorrect type conversions.
See issue #417 for details.
Improvements
-
Permissions, such as microphone and camera, can now be granted to the browser. (#314)
This grants the new browser window permissions that would allow tests to use those devices. You can test the change using the example in examples/grant_permission.js
-
We're also removing the slow-motion option for
Frame.isChecked()
since it doesn't make sense to slow down this sort of check (#376) -
Our log messages are now more concise and user friendlier. (#429)
-
We're working on making xk6-browser available in the k6 Cloud! The feature is still in early testing stages, but we hope to make more announcements about it soon. Stay tuned!
Internals
v0.3.0
xk6-browser v0.3.0 is here! 🎉
This is a minor release with some important bug fixes, a couple of new features, improvements and code refactoring!
New features
-
Implemented
Browser.on(event)
. (#268, #287)on('disconnected')
returns aPromise
you can wait on to get notified when the WebSocket connection to the browser is closed. See this example for details.This is the first async method in xk6-browser, using the newly released event loop support in k6, and marks the start of our transition to async APIs. 🎉
-
Exposed preconfigured mobile device emulation settings. (#289)
We maintain an internal list of popular devices with their viewport size, user agent and scaling factor, which is useful to test how a web site looks and behaves on different devices. See this example for details.
-
Made concealed elements clickable. (#264)
We've added an automatic retry mechanism to improve the reliability of element and pointer actions. We will further improve this in future releases - hence our users' experience.
Bugs fixed
-
Made concealed elements clickable. (#264)
Previously, interacting with an element obscured by another was failing with
wait for selector did not result in any nodes
. Now we properly detect this scenario and retry the action with different scroll positions. This affects allElement
andFrame
click()
,dblclick()
,hover()
,check()
,uncheck()
andtap()
actions. -
Fixed
waitForSelector()
flakiness by retrying once on failure. (#260) -
Fixed data race accessing
Frame.documentHandle
while switching execution contexts. (#263) -
Fixed keyboard press of special keys. (#283)
Previously pressing some keys like Backspace, Delete, ArrowLeft, and AltGraph would panic.
-
Fixed negative metric emission in certain rare scenarios. (#288)
-
Fixed
Page.waitForFunction()
. (#294)waitForFunction()
previously wasn't working. The fix is a rewrite of the feature that ensures all three polling variants work. Validpolling
options are:raf
(default): run the predicate function in arequestAnimationFrame
callback. This will run most frequently, up to 60 times a second.mutation
: run the predicate function on every DOM mutation.- number: run the predicate function at an interval, this many milliseconds apart.
Also note that this is now an async method that returns a
Promise
, so you must usethen()
to resolve it.See this example for details.
-
Fixed
Page.innerHTML()
,Page.innerText()
andPage.textContent()
panic. (#299) -
Fixed the
executablePath
option. (#246)Although you could fill this option out, it wasn't working before, and we were using a predefined path by default. We implemented the option code, and you can now run a Chrome browser of your choice by providing the file path.
Improvements
-
Improved detection of non-clickable elements. (#270)
We now properly detect elements obscured by another element and return an error instead of waiting. This enables the fix in #264.
-
Cleanly close the WebSocket connection when
Browser.close()
is called. (#268) -
Added lifecycle event validation to
Page.waitForLoadState()
. (#300) -
We have started updating our JavaScript API documentation, which we know how important it is to serve as a reference while writing your scripts. This is an ardous task that won't be possible in a couple of weeks, but rest assured we're prioritizing it in all upcoming development cycles, and will be releasing gradual changes as they're done.
-
We added a project roadmap to share our development goals with the community.
Internals
-
Refactored the
chromium
package to fix linter issues and improve code structure. (#246) -
Several code refactors to improve maintainability. (#269, #293)
-
All dependencies were updated to their latest versions. (#274)
Specifically, k6 was updated to v0.38.0, which required us to fix some breaking changes (#286, #302).
v0.2.0
xk6-browser v0.2.0 is here! 🎉
This is a minor release with a few new features, several bug fixes, stability improvements, and overall code cleanup.
New features
-
Support for HTTP Basic Authentication. (#242)
The
BrowserContext
'shttpCredentials
option previously wasn't working (#203).The change also safely handles servers that do not adhere to the basic auth protocol by canceling the authorization process on the first failed attempt.
It also deprecates
BrowserContext.setHttpCredentials
. The correct way of setting the credentials now is creating a newBrowserContext
with credentials:// Correct const context = browser.newContext({ httpCredentials: { username: 'user', password: 'pass', } }); // The following is deprecated context.setHTTPCredentials({ username: 'user', password: 'pass', });
If you need to change or clear credentials within the same script, you should create a new
BrowserContext
. -
Viewport insets now have the correct size on every OS. (#185)
Browser insets change depending on the operating system, and this feature adds support for adjusting insets of the viewport for Windows, Linux, and macOS.
Note that it won't update the viewport if the browser runs in headless mode.
-
Blocking requests based on the remote host's name or IP via k6's
blacklistIPs
andblockHostnames
options. (#204, #205)The browser will block matching requests with an
ERR_BLOCKED_BY_CLIENT
error if the script specifies these options. -
Support for k6's
hosts
option to override DNS resolution with a custom mapping. (#207).This has the same effect as passing the
host-resolver-rules
argument to Chrome via browser args.
Bugs fixed
-
Page.queryAll()
andElement.queryAll()
not finding elements. (#195) -
Possible issue with consecutive clicks on an element if the first click resulted in an exception. (#219)
-
Page.waitForNavigation
becomes unresponsive if the browser or connection is closed or the user cancels the script. We now handle the extension shutting-down stage more robustly, and it shouldn't become unresponsive. (#188) -
Passing arguments to the browser command now works correctly; see this example. (#206)
-
Page.waitForNavigation()
doesn't timeout anymore for navigation within the same document (e.g. via anchor links or the History API). (#247).
Improvements
-
Errors for deprecated Chromium events are no longer printed by default, but can be seen when running in debug mode (
XK6_BROWSER_LOG=debug
). (#251) -
Some error messages were enhanced to aid with debugging. (#193)
Internals
v0.1.3
This release helps us to drive complex websites with xk6-browser by fixing significant frame handling bugs and improving the integration testing suite and logging.
Bugs fixed
-
Fix major bug: Cannot find context with specified id (#49)
FrameSession
was blocking the frame handling mechanism, and the rest of the system couldn't propagate execution contexts, causing the context with specified id not found error. This happens when aSession
is closed while a relatedFrameSession
is booting up.Refactors
FrameSession
and frame handling code. Improves log messages and better reflects the cause of possible errors. -
Fix major bug: Cannot create frame session (#129)
Fixes and gracefully handles cannot create frame session issue reported by #125. It does so by preventing
FrameSession
from throwing an error if the error is temporary and instead logs the error.Improves the handling of creation and destruction of execution contexts in a more stable way.
Fixes related data race issues, refactors and cleans things up.
-
Fix frame aborted navigation event nil pending document sharing (#177)
We were sharing a
nil
pending document when a frame aborts navigation. -
Improve mainframe handling (#174)
This PR skips setting the mainframe if it is already the same. It also adds sanity checks and protects the mainframe field behind a mutex.
Improvements
-
Move WebSocket test server to its own package (#166)
Refactors WebSocket test server and gives it a convenient to use interface:
twss := ws.NewServer(t, ws.WithCDPHandler("/cdp", handler, &cmdsReceived))
-
Revise, refactor, and improve the integration test suite (#140)
This work allows us to reason about the tests better, write them quickly, and provide a first step for reducing circular dependencies between packages. We discovered subtle concurrency bugs thanks to this work. Now we can easily write an integration test like:
newTestBrowser(t) newTestBrowser(t, withFileServer()) // See the issue for more details
Internals
-
Improve execution context logs (#176)
-
Propagate the internal logger to more entities (#151)
Increases the consistency of log messages and adds more detailed log messages to some entities such as
BrowserContext
,FrameManager
,FrameSession
,Page
,Request
, andSession
. -
Update dependencies (#155)
-
Introduce
NewNullLogger
for ease of testing (NewNullLogger)// Old way NewLogger(ctx, NullLogger(), false, nil) // New way NewNullLogger()
v0.1.2
This patch release improves the Playwright compatibility, fixes a few more bugs, and makes extension-wide internal improvements.
Playwright Compatibility
-
Update the flags for launching Chrome. (#148)
Improves the compatibility between xk6-browser and Playwright by updating flags that are internally used when launching a Chrome browser. See the issue for details.
-
Rename
Page.BrintToFront
toPage.BringToFront
. (#131)
Bugs fixed
-
Fix nil interface conversion error in
Frame.document()
. (#149)Since
Frame.document()
is being used by a lot of other functions, this change possibly fixes known and other unknown bugs that may exist inPage.$
,Page.$$
,Frame.Query
,Frame.QueryAll
,Frame.WaitForSelector
, and many other functions. -
Fix special characters not working bug. (#134)
-
Fix parsing of custom remote objects. (#130)
Improvements
-
Improve handling of special characters. (#134)
Some characters can only be produced with special key combinations. For example:
@
can only be produced whenShift
and2
keys are pressed together. This change fixes some missing and incorrect characters in the US keyboard layout, adds shift key detection, improves the error messages, and increases the maintainability of the input handling. -
Improve log handling across the extension components for ease of debugging. (#131)
This change adds log calls to nearly every component across the extension and uses the same logger instance by passing it to a chain of components while launching a browser process.
-
Improve handling and parsing of custom remote objects. (#130)
This change converts remote objects to JSON for producing a safe output when they are used within
console.log()
orEvaluate
calls.