Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Comments

Implement the frameLocator.getBy* methods#5135

Merged
AgnesToulet merged 6 commits intomasterfrom
add/frameLocator-getBy
Sep 12, 2025
Merged

Implement the frameLocator.getBy* methods#5135
AgnesToulet merged 6 commits intomasterfrom
add/frameLocator-getBy

Conversation

@AgnesToulet
Copy link
Contributor

@AgnesToulet AgnesToulet commented Sep 8, 2025

What?

Implement the following frameLocator.getBy* APIs which are the preferred way of working with selectors:

  • frameLocator.getByAltText
  • frameLocator.getByLabel
  • frameLocator.getByPlaceholder
  • frameLocator.getByRole
  • frameLocator.getByTestId
  • frameLocator.getByText
  • frameLocator.getByTitle

Why?

Because we have already implemented all those methods for page, frame, and locator, and we want to implement them as well for frameLocator as a way to increase our compatibility with Playwright, as described in #5036.

Checklist

  • I have performed a self-review of my code.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added tests for my changes.
  • I have run linter and tests locally (make check) and all pass.

Checklist: Documentation (only for k6 maintainers and if relevant)

Please do not merge this PR until the following items are filled out.

  • I have added the correct milestone and labels to the PR.
  • I have updated the release notes: link
  • I have updated or added an issue to the k6-documentation: grafana/k6-docs#NUMBER if applicable
  • I have updated or added an issue to the TypeScript definitions: grafana/k6-DefinitelyTyped#NUMBER if applicable

Related PR(s)/Issue(s)

Closes #5036

@AgnesToulet AgnesToulet requested a review from a team as a code owner September 8, 2025 07:45
@AgnesToulet AgnesToulet requested review from inancgumus and mstoykov and removed request for a team September 8, 2025 07:45
@AgnesToulet AgnesToulet added area: browser browser: playwright related to Playwright compatibility documentation-needed A PR which will need a separate PR for documentation labels Sep 8, 2025
@AgnesToulet AgnesToulet added this to the v1.3.0 milestone Sep 8, 2025
mstoykov
mstoykov previously approved these changes Sep 8, 2025
inancgumus
inancgumus previously approved these changes Sep 8, 2025
Copy link
Contributor

@inancgumus inancgumus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a lovely idea to move the boilerplate testing code into testBrowser 👏. Not related to this PR, but I wonder why we need to load IFrames using an HTTP server when we could do it with a simple iframe srcdoc... I've only added some minor suggestions.


// withIFrameContent sets up a handler for /iframe that serves a page embedding
// an iframe with the given content.
func (tb *testBrowser) withIframeContent(iframeHTML string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IFrame instead of Iframe?

Should this method and withIFrameURL be options that are passed to newTestBrowser, as with other options, for consistency?

tb := newTestBrowser(t, withHTTPServer(), withIFrameContent(...))

Copy link
Contributor Author

@AgnesToulet AgnesToulet Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! withIFrameURL can't be an option because the URL is sometimes known after the testBrowser gets initialized (see https://github.com/grafana/k6/pull/5135/files#diff-7ec25e41d5b272a1ab43d25bb03d48bdd68072ac9632c3295c27f14ce4370011R572-R573) but I refactored withIFrameContent to be an option as it simplifies a bit the locator tests (in 62090aa).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Hmm, don't we already initialize testBrowser before applying the options? The only issue is with withIFrameURL, we'd need to pass that after withHTTPServer.

tbr.applyDefaultOptions()
tbr.applyOptions(opts...) // apply pre-init stage options.
tbr.vu, tbr.cancel = newTestBrowserVU(tb, tbr)
tbr.browserType = chromium.NewBrowserType(tbr.vu)
tbr.vu.ActivateVU()
tbr.isBrowserTypeInitialized = true // some option require the browser type to be initialized.
tbr.applyOptions(opts...) // apply post-init stage options.

<html>
<head></head>
<body>
<iframe id="frameB" src="%s"></iframe>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the frameB id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's used in the tests with the Locator function to retrieve the iframe.

Copy link
Contributor

@inancgumus inancgumus Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd explicitly pass the frame ID to that helper then, as it creates a temporal coupling issue. We'd have to look at that helper code to see why frameB is used in the test every time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 91affdd

"page": any(p).(T),
"frame": any(p.MainFrame()).(T),
"locator": any(p.Locator(":root", nil)).(T),
pageImpl: any(p).(T),
Copy link
Contributor

@inancgumus inancgumus Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR, but I wonder why we use generics here when we could do the same with interfaces, or use a much simpler approach. A task for another time, I guess.

@AgnesToulet AgnesToulet dismissed stale reviews from inancgumus and mstoykov via 62090aa September 9, 2025 08:42
@AgnesToulet
Copy link
Contributor Author

Not related to this PR, but I wonder why we need to load IFrames using an HTTP server when we could do it with a simple iframe srcdoc

I've tested this approach and I like how it simplifies the tests but, I'm not sure why, it makes one test (TestVisibilityWithCORS/visible) in locator_test.go fails. I'll do some other tests with Playwright to see if it's a bug or an expected behavior but I don't think it should be handled in this PR.
@ankur22 Have you looked into this while working on those tests?

mstoykov
mstoykov previously approved these changes Sep 9, 2025
@inancgumus
Copy link
Contributor

inancgumus commented Sep 9, 2025

@AgnesToulet

I've tested this approach and I like how it simplifies the tests but, I'm not sure why, it makes one test (TestVisibilityWithCORS/visible) in locator_test.go fails. I'll do some other tests with Playwright to see if it's a bug or an expected behavior but I don't think it should be handled in this PR.

Adding the allow-same-origin and allow-scripts attributes to the sandbox attribute of iframe can likely solve that issue (e.g., <iframe srcdoc='..' sandbox='allow-same-origin'></iframe>).

@ankur22
Copy link
Contributor

ankur22 commented Sep 10, 2025

Not related to this PR, but I wonder why we need to load IFrames using an HTTP server when we could do it with a simple iframe srcdoc

I've tested this approach and I like how it simplifies the tests but, I'm not sure why, it makes one test (TestVisibilityWithCORS/visible) in locator_test.go fails. I'll do some other tests with Playwright to see if it's a bug or an expected behavior but I don't think it should be handled in this PR.
@ankur22 Have you looked into this while working on those tests?

Might have misunderstood the question, but the reason why we're working with a HTTP server is to mimic a different origin i.e. CORS. Anything in injected_script.js can read from an iframe from the same origin, but if it is a different origin then chrome will prevent it due to CORS. So if we're working with the iframe srcdoc attribute, wouldn't the iframe be from the same origin as the main frame? The assumption in browser is that all content from an iframe is form a different origin. If there's a less complex way then great 👍

Copy link
Contributor

@ankur22 ankur22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀 Thank you! 🙇

@AgnesToulet AgnesToulet merged commit 8799e29 into master Sep 12, 2025
39 checks passed
@AgnesToulet AgnesToulet deleted the add/frameLocator-getBy branch September 12, 2025 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: browser browser: playwright related to Playwright compatibility documentation-needed A PR which will need a separate PR for documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement frameLocator.getBy*

5 participants