UNPKG

@agnos-ui/page-objects

Version:

Page objects to be used when testing AgnosUI-based applications with Playwright.

705 lines (704 loc) 22.6 kB
import { BasePO as l } from "@agnos-ui/base-po"; const p = { // TODO: should we use bootstrap-independent classes starting with au- ? rootComponent: ".modal", closeButton: ".btn-close", backdrop: "xpath=./preceding-sibling::div[contains(@class,'modal-backdrop')]", header: ".modal-header", title: ".modal-title", body: ".modal-body", footer: ".modal-footer" }; class L extends l { selectors = structuredClone(p); getComponentSelector() { return this.selectors.rootComponent; } get locatorHeader() { return this.locatorRoot.locator(this.selectors.header); } get locatorTitle() { return this.locatorHeader.locator(this.selectors.title); } get locatorBody() { return this.locatorRoot.locator(this.selectors.body); } get locatorFooter() { return this.locatorRoot.locator(this.selectors.footer); } get locatorCloseButton() { return this.locatorRoot.locator(this.selectors.closeButton); } get locatorBackdrop() { return this.locatorRoot.locator(this.selectors.backdrop); } async state() { return this.locatorRoot.evaluate((t, e) => { const o = t.querySelector(e.closeButton)?.getAttribute("aria-label"), r = t.querySelector(e.header)?.innerText?.trim(), a = t.querySelector(e.title)?.innerText?.trim(), s = t.querySelector(e.body)?.innerText?.trim(), n = t.querySelector(e.footer)?.innerText?.trim(); return { rootClasses: t.className.trim().split(" ").sort(), header: r, title: a, body: s, footer: n, closeButton: o }; }, this.selectors); } } const y = { rootComponent: ".au-pagination", activePage: ".active", previousPage: ".au-previous", nextPage: ".au-next", firstPage: ".au-first", lastPage: ".au-last", pages: ".au-page", ellipses: ".au-ellipsis" }; class T extends l { selectors = structuredClone(y); // TODO should we add this in the list of selector ? // Depend on the setSelectors usage... getComponentSelector() { return this.selectors.rootComponent; } /** * Gets the locator of the button is the current page in the pagination component. */ get locatorActivePage() { return this.locatorRoot.locator(this.selectors.activePage); } /** * Gets the locator of the button that once clicked moves to the previous page in the pagination component. */ get locatorPreviousButton() { return this.locatorRoot.locator(this.selectors.previousPage); } /** * Gets the locator of the button that once clicked moves to the next page in the pagination component. */ get locatorNextButton() { return this.locatorRoot.locator(this.selectors.nextPage); } /** * Gets the locator of the button that once clicked moves to the first page in the pagination component. */ get locatorFirstButton() { return this.locatorRoot.locator(this.selectors.firstPage); } /** * Gets the locator of the button that once clicked moves to the last page in the pagination component. */ get locatorLastButton() { return this.locatorRoot.locator(this.selectors.lastPage); } /** * Gets the locators of the pages */ get locatorPages() { return this.locatorRoot.locator(this.selectors.pages); } /** * Gets the locator of a page button in the pagination component given his position. * @param pageNumber - The number of the page in the pagination object. */ locatorNthPage(t) { return this.locatorRoot.locator(this.selectors.pages).nth(t - 1); } /** * Gets the locator of a page button in the pagination component given a string. * @param pageString - The string of the page in the pagination object. */ locatorPage(t) { return this.locatorRoot.locator(this.selectors.pages, { hasText: t }); } get locatorEllipses() { return this.locatorRoot.locator(this.selectors.ellipses); } async state() { return this.locatorRoot.evaluate((t) => { const e = { rootClasses: [], disabled: null, pages: [], hrefs: [] }, o = [...t.querySelectorAll(".au-page")], r = [], a = [], s = {}, n = (g) => g?.getAttribute("href"), d = t.querySelector("a.au-first"), u = t.querySelector("a.au-previous"), i = t.querySelector("a.au-next"), h = t.querySelector("a.au-last"); d && (s.first = n(d)), u && (s.previous = n(u)), i && (s.next = n(i)), h && (s.last = n(h)); for (const g of o) a.push(g.getAttribute("href") || ""), r.push((g.textContent || "").trim()); const m = [...t.querySelectorAll("a.au-page[aria-disabled]")]; return e.pages = r, e.hrefs = a, e.hrefsNavigation = s, e.rootClasses = t.className.trim().split(" "), e.disabled = m.length === o.length ? "true" : null, t.querySelector("a.au-previous[aria-disabled]") ? e.isPreviousDisabled = !0 : u && (e.isPreviousDisabled = !1), t.querySelector("a.au-next[aria-disabled]") ? e.isNextDisabled = !0 : i && (e.isNextDisabled = !1), t.querySelector("a.au-first[aria-disabled]") ? e.isFirstDisabled = !0 : d && (e.isFirstDisabled = !1), t.querySelector("a.au-last[aria-disabled]") ? e.isLastDisabled = !0 : h && (e.isLastDisabled = !1), e; }); } } const C = { rootComponent: ".au-rating", star: ".au-rating-star" }; class V extends l { selectors = structuredClone(C); getComponentSelector() { return this.selectors.rootComponent; } /** * Get the main title locator of the feature page */ locatorStar(t) { return this.locatorRoot.locator(this.selectors.star).nth(t); } async state() { return await this.locatorRoot.evaluate((t, e) => { const o = [...t.querySelectorAll(e.star)], r = [], a = []; for (const s of o) r.push((s.textContent || "").trim()), a.push(s.className.split(" ")); return { rootClasses: t.className.trim().split(" ").sort(), value: t.getAttribute("aria-valuenow"), min: t.getAttribute("aria-valuemin"), max: t.getAttribute("aria-valuemax"), text: t.getAttribute("aria-valuetext"), disabled: t.getAttribute("aria-disabled"), readonly: t.getAttribute("aria-readonly"), stars: r, classes: a }; }, this.selectors); } } const x = { rootComponent: ".au-select" // TODO add selector list }; class I extends l { selectors = structuredClone(x); getComponentSelector() { return this.selectors.rootComponent; } /** * Get the main title locator of the feature page */ get locatorInput() { return this.locatorRoot.locator('input[type="text"]').nth(0); } /** * Menu container */ get locatorMenu() { return this.locatorRoot.locator(".dropdown-menu"); } /** * Return the first menu item locator including the text */ get locatorMenuItems() { return this.locatorMenu.locator(".au-select-item"); } /** * Return the first menu item locator including the text */ locatorMenuItem(t) { return this.locatorMenu.getByText(t).nth(0); } /** * Bages container */ get locatorBadges() { return this.locatorRoot.locator("div.au-select-badge"); } /** * Return the first badge locator including the text */ locatorBadgeItem(t) { return this.locatorBadges.filter({ hasText: t }).nth(0); } async state() { return await this.locatorRoot.evaluate((t) => { const e = t.querySelector('div[role="combobox"]'), o = t.querySelector('input[type="text"]'), r = []; if (e) { const u = e.querySelectorAll("div.au-select-badge"); for (const i of u) r.push(i?.textContent?.trim()); } const a = t.querySelector("ul.dropdown-menu"), s = a != null, n = [], d = []; if (a != null) { const u = a.querySelectorAll("li.dropdown-item"); for (const i of u) { const h = i.textContent?.trim(); n.push(h), i.classList.contains("selected") && d.push(h); } } return { text: o.value, badges: r, isOpen: s, list: n, checked: d }; }); } } const S = { rootComponent: ".alert", body: ".alert-body", closeButton: ".btn-close" }; class O extends l { selectors = structuredClone(S); getComponentSelector() { return this.selectors.rootComponent; } get locatorCloseButton() { return this.locatorRoot.locator(this.selectors.closeButton); } async state() { return this.locatorRoot.evaluate((t, e) => { const o = t.querySelector(e.body)?.innerText?.replace(/[^\x20-\x7E]/g, ""), r = t.querySelector(e.closeButton)?.getAttribute("aria-label"); return { rootClasses: t.className.trim().split(" ").sort(), body: o, closeButton: r }; }, this.selectors); } } class H extends l { selectors = { item: ".accordion-item", bodyContainer: ".accordion-collapse", body: ".accordion-body", header: ".accordion-header", buttons: ".accordion-button" }; getComponentSelector() { return ".au-accordion"; } /** * Gets the locators of the items containing the header and the body-container inside * the accordion */ get locatorAccordionItems() { return this.locatorRoot.locator(this.selectors.item); } /** * Gets the locators of the item specified by the itemIndex containing the header and the body-container inside * the accordion */ locatorAccordionItem(t) { return this.locatorRoot.locator(this.selectors.item).nth(t); } get locatorAccordionCBodyContainers() { return this.locatorAccordionItems.locator(this.selectors.bodyContainer); } locatorAccordionBodyContainer(t) { return this.locatorAccordionItem(t).locator(this.selectors.bodyContainer); } /** * Gets the locator of the bodies of the accordion. */ get locatorAccordionBodies() { return this.locatorAccordionCBodyContainers.locator(this.selectors.body); } locatorAccordionBody(t) { return this.locatorAccordionBodyContainer(t).locator(this.selectors.body); } get locatorAccordionHeaders() { return this.locatorAccordionItems.locator(this.selectors.header); } locatorAccordionHeader(t) { return this.locatorAccordionItem(t).locator(this.selectors.header); } /** * Gets the locators of the buttons that handle the accordion, present in the accordion header. * It does not get the locators of the buttons present in the body, added by the developer. */ get locatorAccordionButtons() { return this.locatorAccordionHeaders.locator(this.selectors.buttons); } locatorAccordionButton(t) { return this.locatorAccordionHeader(t).locator(this.selectors.buttons); } async state() { return await this.locatorRoot.evaluate((t) => { const e = [...t.querySelectorAll(".accordion-item")], o = []; for (const r of e) { const a = r.querySelector(".accordion-collapse"), s = r.querySelector(".accordion-button"); o.push({ classes: r.className.trim().split(" "), id: r.id, isInDOM: a !== null, bodyContainerId: a?.id, buttonId: s?.id, expanded: s?.getAttribute("aria-expanded"), disabled: s?.getAttribute("aria-disabled"), labeledBy: a?.getAttribute("aria-labelledby"), buttonControls: s?.getAttribute("aria-controls") }); } return { rootClasses: t.className.trim().split(" "), items: o }; }); } } const A = { rootComponent: '[role="progressbar"]', outerBar: ".progress", innerBar: ".progress-bar" }; class M extends l { selectors = structuredClone(A); getComponentSelector() { return this.selectors.rootComponent; } get locatorOuterBar() { return this.locatorRoot.locator(this.selectors.outerBar); } get locatorInnerBar() { return this.locatorRoot.locator(this.selectors.innerBar); } async state() { return this.locatorRoot.evaluate((t) => { const e = t.querySelector(".progress-bar"), o = t.querySelector(".progress"); return { ariaLabel: t.getAttribute("aria-label"), ariaValueNow: t.getAttribute("aria-valuenow"), ariaValueMin: t.getAttribute("aria-valuemin"), ariaValueMax: t.getAttribute("aria-valuemax"), ariaValueText: t.getAttribute("aria-valuetext"), label: e?.textContent?.trim(), innerClasses: e?.className?.trim()?.split(" ")?.sort() ?? [], outerHeight: o?.style?.height, innerWidth: e?.style?.width }; }); } } const R = { rootComponent: ".au-slider", clickableArea: ".au-slider-clickable-area", clickableAreaVertical: ".au-slider-clickable-area-vertical", handle: ".au-slider-handle", tick: ".au-slider-tick", tickLabel: ".au-slider-tick-label", tickLabelVertical: ".au-slider-tick-label-vertical", tickLabelNow: ".au-slider-tick-label-now", minLabelHorizontal: ".au-slider-label-min", maxLabelHorizontal: ".au-slider-label-max", minLabelVertical: ".au-slider-label-vertical-min", maxLabelVertical: ".au-slider-label-vertical-max", valueLabel: ".au-slider-label-now", progress: ".au-slider-progress", content: ".au-slider-content" }; class E extends l { selectors = structuredClone(R); getComponentSelector() { return this.selectors.rootComponent; } get clickableArea() { return this.locatorRoot.locator(this.selectors.clickableArea); } get clickableAreaVertical() { return this.locatorRoot.locator(this.selectors.clickableAreaVertical); } get locatorHandle() { return this.locatorRoot.locator(this.selectors.handle); } get locatorTick() { return this.locatorRoot.locator(this.selectors.tick); } get locatorTickLabel() { return this.locatorRoot.locator(this.selectors.tickLabel); } get locatorTickLabelNow() { return this.locatorRoot.locator(this.selectors.tickLabelNow); } get locatorTickLabelVertical() { return this.locatorRoot.locator(this.selectors.tickLabelVertical); } get locatorMinLabelHorizontal() { return this.locatorRoot.locator(this.selectors.minLabelHorizontal); } get locatorMaxLabelHorizontal() { return this.locatorRoot.locator(this.selectors.maxLabelHorizontal); } get locatorMinLabelVertical() { return this.locatorRoot.locator(this.selectors.minLabelVertical); } get locatorMaxLabelVertical() { return this.locatorRoot.locator(this.selectors.maxLabelVertical); } get locatorProgress() { return this.locatorRoot.locator(this.selectors.progress); } get locatorValueLabel() { return this.locatorRoot.locator(this.selectors.valueLabel); } get locatorContent() { return this.locatorRoot.locator(this.selectors.content); } async sliderHandleState() { return this.locatorRoot.locator(this.selectors.handle).evaluateAll((t) => t.map((e) => ({ style: e.getAttribute("style"), value: e.getAttribute("aria-valuenow"), min: e.getAttribute("aria-valuemin"), max: e.getAttribute("aria-valuemax"), disabled: e.getAttribute("aria-disabled"), readonly: e.getAttribute("aria-readonly"), ariaLabel: e.getAttribute("aria-label"), ariaValueText: e.getAttribute("aria-valuetext") }))); } async sliderProgressState() { return this.locatorRoot.locator(this.selectors.progress).evaluateAll((t) => t.map((e) => e.getAttribute("style"))); } /** * Get the state of the tick elements * @param locator tick locator (horizontal or vertical) * @returns state of all the ticks */ async sliderTickLabelState(t) { return t.evaluateAll((e) => e.map((o) => ({ style: o.getAttribute("style"), innerText: o.innerText }))); } } const b = { rootComponent: ".toast", closeButton: ".btn-close", header: ".toast-header", body: ".toast-body" }; class v extends l { selectors = structuredClone(b); getComponentSelector() { return this.selectors.rootComponent; } get locatorCloseButton() { return this.locatorRoot.locator(this.selectors.closeButton); } async state() { return await this.locatorRoot.evaluate((t, e) => { const o = t.querySelector(e.body)?.innerText, r = t.querySelector(e.header)?.innerText, a = t.querySelector(e.closeButton)?.getAttribute("aria-label"); return { rootClasses: t.className.trim().split(" ").sort(), body: o, header: r, closeButton: a }; }, this.selectors); } } const B = { rootComponent: ".au-toaster", container: ".au-toaster-container", closeButton: ".au-toaster-closeAll" }; class z extends l { selectors = structuredClone(B); getComponentSelector() { return this.selectors.rootComponent; } get locatorContainer() { return this.locatorRoot.locator(this.selectors.container); } async toastPOs() { return Array.from( { length: await this.locatorContainer.locator(b.rootComponent).count() }, (t, e) => new v(this.locatorContainer, e) ); } get locatorCloseButton() { return this.locatorRoot.locator(this.selectors.closeButton); } } const f = { rootComponent: '[role="tree"]', itemContainer: '[role="treeitem"]', itemToggle: ".au-tree-expand-icon", itemContents: ".au-tree-item" }; class D extends l { selectors = structuredClone(f); getComponentSelector() { return this.selectors.rootComponent; } get locatorItemToggle() { return this.locatorRoot.locator(this.selectors.itemToggle); } get locatorItemContainer() { return this.locatorRoot.locator(this.selectors.itemContents); } async itemContainerState() { return this.locatorRoot.locator(this.selectors.itemContainer).evaluateAll((t) => t.map((e) => ({ ariaSelected: e.getAttribute("aria-selected"), ariaExpanded: e.getAttribute("aria-expanded") }))); } async itemToggleState() { return this.locatorRoot.locator(this.selectors.itemToggle).evaluateAll((t) => t.map((e) => ({ ariaLabel: e.getAttribute("aria-label") }))); } } const P = { rootComponent: ".au-collapse" }; class F extends l { selectors = structuredClone(P); getComponentSelector() { return this.selectors.rootComponent; } async state() { return this.locatorRoot.evaluate((t, e) => ({ rootClasses: t.className.trim().split(" ").sort() }), this.selectors); } } const q = { rootComponent: ".au-carousel", container: ".au-carousel-container", slide: ".au-carousel-slide", nextBtn: ".carousel-control-next", prevBtn: ".carousel-control-prev", indicators: ".carousel-indicators", indicatorBtn: ".carousel-indicators button" }; class _ extends l { selectors = structuredClone(q); getComponentSelector() { return this.selectors.rootComponent; } get locatorContainer() { return this.locatorRoot.locator(this.selectors.container); } get locatorNextBtn() { return this.locatorRoot.locator(this.selectors.nextBtn); } get locatorPrevBtn() { return this.locatorRoot.locator(this.selectors.prevBtn); } get locatorIndicators() { return this.locatorRoot.locator(this.selectors.indicators); } get locatorIndicatorBtn() { return this.locatorRoot.locator(this.selectors.indicatorBtn); } get locatorSlide() { return this.locatorRoot.locator(this.selectors.slide); } async state() { return this.locatorRoot.evaluate((t) => { const e = t.querySelectorAll(".carousel-indicators button"); return { rootClasses: t.className.trim().split(" ").sort(), prevBtn: t.querySelector(".carousel-control-prev") !== null, nextBtn: t.querySelector(".carousel-control-next") !== null, indicators: { selected: [...e].findIndex((o) => o.classList.contains("active")), count: e.length }, slides: { visible: [...t.querySelectorAll(".au-carousel-slide")].findIndex((o) => { const r = o.getBoundingClientRect(), a = t.getBoundingClientRect(); return r.left >= a.left && r.right <= a.right; }) } }; }); } } const w = { rootComponent: ".au-drawer", backdrop: "xpath=./preceding-sibling::div[contains(@class,'au-drawer-backdrop')]", header: ".au-drawer-header", body: ".au-drawer-body", container: ".au-drawer-container", splitter: ".au-splitter", closeButton: "Close" }; class W extends l { selectors = structuredClone(w); getComponentSelector() { return this.selectors.rootComponent; } get locatorHeader() { return this.locatorRoot.locator(this.selectors.header); } get locatorBody() { return this.locatorRoot.locator(this.selectors.body); } get locatorBackdrop() { return this.locatorRoot.locator(this.selectors.backdrop); } get locatorContainer() { return this.locatorRoot.locator(this.selectors.container); } get locatorSplitter() { return this.locatorRoot.locator(this.selectors.splitter); } get locatorCloseButton() { return this._page.getByRole("button", { name: "Close" }); } /** * Hovers the mouse over the center of a splitter element. * * @returns A promise that resolves to an object containing the absolute x and y coordinates * of the hover position */ async hoverOnSplitter() { const t = this.locatorSplitter, e = await t.boundingBox(), o = Math.round(e.width / 2), r = Math.round(e.height / 2); return await t.hover({ position: { x: o, y: r } }), { x: e.x + o, y: e.y + r }; } async state() { return this.locatorRoot.evaluate((t, e) => { const o = t.querySelector(e.header)?.innerText?.trim(), r = t.querySelector(e.body)?.innerText?.trim(); return { rootClasses: t.className.trim().split(" ").sort(), header: o, body: r }; }, this.selectors); } async statePosition() { return this.locatorRoot.evaluate((t) => { const e = t.style; return { "--bs-drawer-size": e.getPropertyValue("--bs-drawer-size"), "--bs-drawer-size-min": e.getPropertyValue("--bs-drawer-size-min"), "--bs-drawer-size-max": e.getPropertyValue("--bs-drawer-size-max") }; }); } } export { H as AccordionPO, O as AlertPO, _ as CarouselPO, F as CollapsePO, W as DrawerPO, L as ModalPO, T as PaginationPO, M as ProgressbarPO, V as RatingPO, I as SelectPO, E as SliderPO, v as ToastPO, z as ToasterPO, D as TreePO, S as alertSelectors, q as carouselSelectors, P as collapseSelectors, w as drawerSelectors, p as modalSelectors, y as paginationSelectors, A as progressbarSelectors, C as ratingSelectors, x as selectSelectors, R as sliderSelectors, b as toastSelectors, B as toasterSelectors, f as treeSelectors };