UNPKG

playwright-testing-library

Version:
124 lines 6.52 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.synchronousQueryNames = exports.screenFor = exports.queriesFor = exports.isNotFindQuery = exports.isAllQuery = exports.allQueryNames = exports.LocatorPromise = void 0; const test_1 = require("@playwright/test"); const dom_1 = require("@testing-library/dom"); const helpers_1 = require("../helpers"); const helpers_2 = require("./helpers"); const isAllQuery = (query) => query.includes('All'); exports.isAllQuery = isAllQuery; const isFindQuery = (query) => query.startsWith('find'); const isNotFindQuery = (query) => !query.startsWith('find'); exports.isNotFindQuery = isNotFindQuery; const allQueryNames = Object.keys(dom_1.queries); exports.allQueryNames = allQueryNames; const synchronousQueryNames = allQueryNames.filter(isNotFindQuery); exports.synchronousQueryNames = synchronousQueryNames; const findQueryToGetQuery = (query) => query.replace(/^find/, 'get'); const findQueryToQueryQuery = (query) => query.replace(/^find/, 'query'); class LocatorPromise extends Promise { constructor(executor, config) { super(executor); this.config = config; } /** * Wrap an `async` function `Promise` return value in a `LocatorPromise`. * This allows us to use `async/await` and still return a custom * `LocatorPromise` instance instead of `Promise`. * * @param fn * @returns */ static wrap(fn, config) { return (...args) => LocatorPromise.from(fn(...args), config); } static from(promise, config) { return new LocatorPromise((resolve, reject) => { promise.then(resolve).catch(reject); }, config); } within() { // eslint-disable-next-line @typescript-eslint/no-use-before-define return queriesFor(this, this.config); } } exports.LocatorPromise = LocatorPromise; const locatorFor = (root, query, options) => root.locator(`${(0, helpers_2.queryToSelector)(query)}=${JSON.stringify(options, helpers_1.replacer)}`); const augmentedLocatorFor = (root, query, options, config) => { const locator = locatorFor(root, query, options); return new Proxy(locator, { get(target, property, receiver) { return property === 'within' ? // eslint-disable-next-line @typescript-eslint/no-use-before-define () => queriesFor(target, config) : Reflect.get(target, property, receiver); }, }); }; const createFindQuery = (root, query, { asyncUtilTimeout, asyncUtilExpectedState } = {}) => LocatorPromise.wrap((...[id, options, waitForElementOptions]) => __awaiter(void 0, void 0, void 0, function* () { const settledRoot = root instanceof LocatorPromise ? yield root : root; const synchronousOptions = (options ? [id, options] : [id]); const locator = locatorFor(settledRoot, findQueryToQueryQuery(query), synchronousOptions); const { state: expectedState = asyncUtilExpectedState, timeout = asyncUtilTimeout } = waitForElementOptions !== null && waitForElementOptions !== void 0 ? waitForElementOptions : {}; try { yield locator.first().waitFor({ state: expectedState, timeout }); } catch (error) { // In the case of a `waitFor` timeout from Playwright, we want to // surface the appropriate error from Testing Library, so run the // query one more time as `get*` knowing that it will fail with the // error that we want the user to see instead of the `TimeoutError` if (error instanceof test_1.errors.TimeoutError) { const timeoutLocator = locatorFor(settledRoot, findQueryToGetQuery(query), synchronousOptions).first(); // Handle case where element is attached, but hidden, and the expected // state is set to `visible`. In this case, dereferencing the // `Locator` instance won't throw a `get*` query error, so just // surface the original Playwright timeout error if (expectedState === 'visible' && !(yield timeoutLocator.isVisible())) { throw error; } // In all other cases, dereferencing the `Locator` instance here should // cause the above `get*` query to throw an error in Testing Library yield timeoutLocator.waitFor({ state: expectedState, timeout }); } } return locator; }), { asyncUtilExpectedState, asyncUtilTimeout }); /** * Given a `Page` or `Locator` instance, return an object of Testing Library * query methods that return a `Locator` instance for the queried element * * @internal this API is not currently intended for public usage and may be * removed or changed outside of semantic release versioning. If possible, you * should use the `locatorFixtures` with **@playwright/test** instead. * @see {@link locatorFixtures} * * @param root `Page` or `Locator` instance to use as the query root * @param config Testing Library configuration to apply to queries * * @returns object containing scoped Testing Library query methods */ const queriesFor = (root, config) => allQueryNames.reduce((rest, query) => (Object.assign(Object.assign({}, rest), { [query]: isFindQuery(query) ? createFindQuery(root, query, config) : (...options) => root instanceof LocatorPromise ? root.then(r => locatorFor(r, query, options)) : augmentedLocatorFor(root, query, options, config) })), {}); exports.queriesFor = queriesFor; const screenFor = (page, config) => Proxy.revocable(page, { get(target, property, receiver) { return (0, helpers_2.includes)(allQueryNames, property) ? queriesFor(page, config)[property] : Reflect.get(target, property, receiver); }, }); exports.screenFor = screenFor; //# sourceMappingURL=queries.js.map