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
[browser] Provide access to Playwright's Keyboard classes in browser mode #4918
Comments
Thanks for the feature request. To make sure I understand this better, can you elaborate on what kind of tests you are intending to write on Vitest browser mode if such API is available? Providing some examples with your hypothetical API might help.
One important difference between Vitest's browser mode and Playwright is that "test suite" itself is executed on the browser on Vitest browser mode. It might be obvious, just in case, to give a concrete example: // vitest browser mode
test("test", () => {
expect(typeof window).toBe("object")
})
// playwright
test("test", async ({ page }) => {
expect(typeof window).toBe("undefined")
expect(await page.evaluate(() => typeof window)).toBe("object") // page API is the interface to the browser
}) I think the better analogy would be that it's jsdom-like test environment but it's actually the real browser. So, it might make more sense to bring something like testing-library ecosystem https://testing-library.com/docs/ for selector, event utility etc... (actually I've never tried, but I feel it makes sense). |
The idea is that people use solutions that are already provided by third-party packages. Eventually, Vitest should provide a set of utilities that are better addressed natively (like clicking - it's not possible to emulate the order of all events on the micro-task level specified by the spec). The API for this is not decided yet - I feel like we should make the runner more stable before starting with this. |
Thanks for sharing the plan. I also wanted to mention that if this PR #3584 eventually runs multiple test files (in parallel?) under separate iframes but are managed by single "page" instance, then exposing something in terms of provider's page interface level wouldn't make sense probably. |
@hi-ogawa I guess I already provided a use case by mentioning it('focuses the element correctly', async () => {
const el = await fixture(html`<my-element></my-element>`);
expect(
el.shadowRoot?.querySelector('a[href="https://vitejs.dev"]')
).toBeInTheDocument();
(
el.shadowRoot?.querySelector(
'a[href="https://vitejs.dev"]'
) as HTMLAnchorElement
)?.focus();
expect(
el.shadowRoot?.activeElement?.isEqualNode(
el.shadowRoot?.querySelector('a[href="https://vitejs.dev"]')
)
).true;
/**
* fixme: None of these can simulate a keypress tab to focus an element on the screen.
*/
// document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' }));
// document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Tab' }));
document.dispatchEvent(new KeyboardEvent('keypress', { key: 'Tab' }));
// el.shadowRoot?.activeElement?.dispatchEvent(
// new KeyboardEvent('keypress', { key: 'Tab' })
// );
expect(
el.shadowRoot?.activeElement?.isEqualNode(
el.shadowRoot?.querySelector('a[href="https://lit.dev"]')
)
).true;
}); I could be wrong but simulating a keypress // None of these works to simulate keypress tab
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' }));
document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Tab' }));
document.dispatchEvent(new KeyboardEvent('keypress', { key: 'Tab' }));
document.shadowRoot?.activeElement?.dispatchEvent(new KeyboardEvent('keypress', { key: 'Tab' })); So, the proposed solution is to make use of the Playwright's Keyboard class allows users to simulate keyboard inputs as if they were generated from a real keyboard, e.g. There's already a prior art from the it('focuses next element', async () => {
// ...
await sendKeys({ press: 'Tab' });
// ...
}); Hope this helps. |
@motss Thanks for taking a time to put together a sample! The concerns I have with exposing playwright API (or any browser driver level features) is that, for one, I don't think it's so simple to implement it on Vitest browser mode since the code is executed in a different layer as I mentioned in my first comment #4918 (comment) For 2nd, related to our plan of running multiple test files isolated in different iframes (but still in a single page managed by browser driver), it would probably makes it complicated to expose some browser driver features directly. Nonetheless, I appreciate you sharing the idea. We'll probably get some inspirations from existing API and implementations, so it would be helpful in the future. |
I do like the import { sendKeys } from '$page'
await sendKeys({ type: 'hello world' }) On the server side, we can implement some kind of API to get this virtual module from testing providers: interface VirtualBrowserPage {
sendKeys(options): void
}
interface BrowserProvider {
getVirtualPageMethods() {
return { sendKeys: this.sendKeys }
}
} And the virtual module is generated based on the returned keys: const plugin = {
resolveId(id) {
if(id === '$page') {
return '\0$page'
}
},
load(id) {
if(id === '\0$page') {
const page = provider.getVirtualPageMethods()
const methods = Object.keys(page)
return `
const rpc = () => __vitest_worker__.rpc
${methods.map(method => `export const ${method} = (...args) => rpc().page(${method}, ...args)`}
`
}
}
} |
Clear and concise description of the problem
The experimental browser mode currently allows users to choose a list of providers (Webdriver.io, Playwright) to run their tests on various browsers supported by their chosen provider.
However, there isn't a way to reference the current page context in a test suite to call some of the API classes offered by Playwright, e.g. the Playwright's Keyboard class allows users to simulate keyboard inputs as if they were generated from a real keyboard.
Suggested solution
Alternative
No response
Additional context
No response
Validations
The text was updated successfully, but these errors were encountered: