@arcgis/lumina-compiler 4.31.0-next.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +13 -0
- package/README.md +21 -0
- package/dist/chunk-BQ4U6HQL.js +1 -0
- package/dist/chunk-JFKSI6I7.js +1 -0
- package/dist/context/index.d.ts +241 -0
- package/dist/context/types.d.ts +34 -0
- package/dist/context/utils.d.ts +23 -0
- package/dist/context/utils.spec.d.ts +1 -0
- package/dist/defaultAssetsUrl.d.ts +21 -0
- package/dist/defaultAssetsUrl.spec.d.ts +1 -0
- package/dist/dependencies/arcgisCore.d.ts +30 -0
- package/dist/dependencies/discover.d.ts +62 -0
- package/dist/dependencies/index.d.ts +11 -0
- package/dist/dependencies/lit.d.ts +2 -0
- package/dist/dependencies/loaders.d.ts +8 -0
- package/dist/dependencies/stencil.d.ts +6 -0
- package/dist/dependencies/testSetupFiles.d.ts +21 -0
- package/dist/dependencies/updateLumina.d.ts +8 -0
- package/dist/dependencies/updateLumina.spec.d.ts +1 -0
- package/dist/dependencies/utils.d.ts +23 -0
- package/dist/entrypoints/addNonLazyImports.d.ts +13 -0
- package/dist/entrypoints/config.d.ts +23 -0
- package/dist/entrypoints/dtsUtils.d.ts +22 -0
- package/dist/entrypoints/dtsUtils.spec.d.ts +1 -0
- package/dist/entrypoints/findUtils.d.ts +21 -0
- package/dist/entrypoints/findUtils.spec.d.ts +1 -0
- package/dist/entrypoints/handleComponentImports.d.ts +13 -0
- package/dist/entrypoints/pathMapping.d.ts +25 -0
- package/dist/entrypoints/resolveTagName.d.ts +14 -0
- package/dist/entrypoints/resolveTagName.spec.d.ts +1 -0
- package/dist/frameworkTypes/index.d.ts +15 -0
- package/dist/frameworkTypes/lumina.d.ts +5 -0
- package/dist/frameworkTypes/preact.d.ts +6 -0
- package/dist/frameworkTypes/react.d.ts +6 -0
- package/dist/frameworkTypes/stencil.d.ts +5 -0
- package/dist/frameworkTypes/utils.d.ts +8 -0
- package/dist/frameworkTypes/vanilla.d.ts +3 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +248 -0
- package/dist/jsxToLitHtml/autoAddNothing.d.ts +8 -0
- package/dist/jsxToLitHtml/comments.d.ts +19 -0
- package/dist/jsxToLitHtml/config.d.ts +148 -0
- package/dist/jsxToLitHtml/convertProps.d.ts +10 -0
- package/dist/jsxToLitHtml/escapeForTemplateLiteral.d.ts +45 -0
- package/dist/jsxToLitHtml/imports.d.ts +32 -0
- package/dist/jsxToLitHtml/index.d.ts +17 -0
- package/dist/jsxToLitHtml/inferPropType.d.ts +40 -0
- package/dist/jsxToLitHtml/insertRepeatCall.d.ts +49 -0
- package/dist/jsxToLitHtml/jsxVisitor.d.ts +11 -0
- package/dist/jsxToLitHtml/templateParts.d.ts +17 -0
- package/dist/jsxToLitHtml/throwOnImportingExternalized.d.ts +10 -0
- package/dist/jsxToLitHtml/types.d.ts +80 -0
- package/dist/jsxToLitHtml/utils.d.ts +14 -0
- package/dist/jsxToLitHtml/utils.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/addComponentMetadata.d.ts +5 -0
- package/dist/manifests/complexTypes/addMethodMetadata.d.ts +6 -0
- package/dist/manifests/complexTypes/addPropMetadata.d.ts +8 -0
- package/dist/manifests/complexTypes/docsUtils.d.ts +18 -0
- package/dist/manifests/complexTypes/event.d.ts +9 -0
- package/dist/manifests/complexTypes/getComplexPropertyType.d.ts +11 -0
- package/dist/manifests/complexTypes/transformUtils.d.ts +130 -0
- package/dist/manifests/complexTypes/transformUtils.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/typeToEnum.d.ts +14 -0
- package/dist/manifests/complexTypes/typeToEnum.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/types.d.ts +135 -0
- package/dist/manifests/config.d.ts +2 -0
- package/dist/manifests/createManifest.d.ts +39 -0
- package/dist/manifests/customElementDecoratorPlugins.d.ts +58 -0
- package/dist/manifests/customElementDecoratorPlugins.spec.d.ts +1 -0
- package/dist/manifests/hideUntilHydrated.d.ts +15 -0
- package/dist/manifests/index.d.ts +12 -0
- package/dist/manifests/kebabCaseAttributes.d.ts +18 -0
- package/dist/manifests/lazy.d.ts +22 -0
- package/dist/manifests/lazy.spec.d.ts +1 -0
- package/dist/manifests/stencilManifest.d.ts +17 -0
- package/dist/manifests/storybookManifest.d.ts +6 -0
- package/dist/manifests/types.d.ts +1 -0
- package/dist/manifests/utils.d.ts +17 -0
- package/dist/plugins/buildCdn.d.ts +14 -0
- package/dist/plugins/buildStencilHydrate.d.ts +16 -0
- package/dist/plugins/buildWrappers.d.ts +3 -0
- package/dist/plugins/configureVite.d.ts +19 -0
- package/dist/plugins/externalizeDependencies.d.ts +34 -0
- package/dist/plugins/externalizeDependencies.spec.d.ts +1 -0
- package/dist/plugins/generateDocs.d.ts +10 -0
- package/dist/plugins/handleDynamicAssets.d.ts +3 -0
- package/dist/plugins/handleStaticAssets.d.ts +9 -0
- package/dist/plugins/loadLitCss.d.ts +89 -0
- package/dist/plugins/printTotalBuildSize.d.ts +7 -0
- package/dist/plugins/provideAssets.d.ts +53 -0
- package/dist/plugins/provideAssets.spec.d.ts +1 -0
- package/dist/plugins/setAssetsPath.d.ts +10 -0
- package/dist/plugins/updatePackageJson.d.ts +9 -0
- package/dist/plugins/updatePackageJson.spec.d.ts +1 -0
- package/dist/publicTypes.d.ts +626 -0
- package/dist/puppeteer-testing/globalSetup.d.ts +72 -0
- package/dist/puppeteer-testing/globalSetup.js +11 -0
- package/dist/puppeteer-testing/index.d.ts +9 -0
- package/dist/puppeteer-testing/index.js +6 -0
- package/dist/puppeteer-testing/injected.d.ts +8 -0
- package/dist/puppeteer-testing/puppeteer/browser.d.ts +6 -0
- package/dist/puppeteer-testing/puppeteer/element.d.ts +219 -0
- package/dist/puppeteer-testing/puppeteer/events.d.ts +21 -0
- package/dist/puppeteer-testing/puppeteer/page.d.ts +5 -0
- package/dist/puppeteer-testing/puppeteer/types.d.ts +124 -0
- package/dist/puppeteer-testing/vitest/matchers/attributes.d.ts +4 -0
- package/dist/puppeteer-testing/vitest/matchers/classList.d.ts +4 -0
- package/dist/puppeteer-testing/vitest/matchers/events.d.ts +7 -0
- package/dist/puppeteer-testing/vitest/matchers/index.d.ts +38 -0
- package/dist/puppeteer-testing/vitest/matchers/text.d.ts +2 -0
- package/dist/puppeteer-testing/vitest/matchers/utils.d.ts +1 -0
- package/dist/puppeteer-testing/vitest/runner.d.ts +15 -0
- package/dist/puppeteer-testing/vitest/setupFile.d.ts +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/mount.d.ts +106 -0
- package/dist/testing/setupFile.d.ts +1 -0
- package/dist/testing/snapshotSerializer.d.ts +12 -0
- package/dist/testing/wrapController.d.ts +33 -0
- package/dist/tests/utils.d.ts +4 -0
- package/dist/transformers/guardAgainstInternalJsDoc.d.ts +11 -0
- package/dist/transformers/index.d.ts +22 -0
- package/dist/transformers/injectRuntimeOptions.d.ts +3 -0
- package/dist/transformers/internalTypeScriptApis.d.ts +29 -0
- package/dist/transformers/liftDecorators.d.ts +21 -0
- package/dist/transformers/members.d.ts +12 -0
- package/dist/transformers/property.d.ts +9 -0
- package/dist/transformers/propertyOptions.d.ts +111 -0
- package/dist/transformers/updateOriginalFile.d.ts +20 -0
- package/dist/transformers/utils.d.ts +14 -0
- package/dist/types/astTransformers.d.ts +3 -0
- package/dist/types/hideInternalLitElement.d.ts +9 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/liftSetterTypes.d.ts +33 -0
- package/dist/types/textTransformers.d.ts +4 -0
- package/dist/types/transformComponentMembers.d.ts +10 -0
- package/dist/useLumina.d.ts +13 -0
- package/dist/utils/error.d.ts +4 -0
- package/dist/utils/packageJson.d.ts +24 -0
- package/dist/utils/path.d.ts +25 -0
- package/dist/utils/path.spec.d.ts +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import"../chunk-JFKSI6I7.js";import{launch as l}from"puppeteer";import{createServer as a}from"vite";async function f(e){let[t,o]=await Promise.all([p(e),d(e)]);return async()=>{await Promise.all([o.close(),t.close()])}}async function p(e){let t=e.config.puppeteerLaunchOptions??{},o=!!e.config.inspector.enabled,r=1e3*60*60,n={devtools:o,acceptInsecureCerts:!0,protocolTimeout:t.devtools?r:void 0,...t},s=await l(n),i={...n,browserWSEndpoint:s.wsEndpoint()};return e.provide("puppeteerConnectOptions",i),e.provide("isDevToolsEnabled",t.devtools??!1),e.provide("isHeadlessBrowser",t.headless===void 0?t.devtools!==!0:t.headless!==!1),s}async function d(e){let t={__IS_IN_PUPPETEER__:!0},o=await a({logLevel:"error",server:{open:!1},root:e.config.root,mode:e.config.mode,clearScreen:!1,define:t});return await o.listen(),await v(e,o),c(e,o),o}async function v(e,t){let o=await t.transformIndexHtml("/",`<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<link rel="icon" href="data:;base64,=" />
|
|
7
|
+
<title>E2E Tests</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
</body>
|
|
11
|
+
</html>`);e.provide("devServerHtml",o)}function c(e,t){let o=t.resolvedUrls,r=o?.local.at(0)??o?.network.at(0);if(r===void 0)throw new Error("Failed to resolve the dev server URL");e.provide("devServerUrl",r)}export{f as setup};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type * from "./puppeteer/types";
|
|
2
|
+
export { newE2EPage } from "./puppeteer/page";
|
|
3
|
+
export { setupPuppeteerTest } from "./vitest/setupFile";
|
|
4
|
+
/**
|
|
5
|
+
* This has to be default export for Vitest to discover it
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/vitest-dev/vitest/blob/699055eb93909287e1542fdfb99d97f2a38965ba/packages/vitest/src/runtime/runners/index.ts#L25
|
|
8
|
+
*/
|
|
9
|
+
export { PuppeteerTestRunner as default } from "./vitest/runner";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{a as _,c as R}from"../chunk-BQ4U6HQL.js";import"../chunk-JFKSI6I7.js";async function C(t){await t.exposeFunction("puppeteerOnEvent",(i,e)=>{Y(t._e2eEvents,i,e)}),await t.evaluateOnNewDocument(Q)}async function S(t,i,e){let n=new h(i),r=e!=="document"?()=>window:()=>document,s=await t.evaluateHandle(r);return await E(t,s,i,a=>{n.push(a)}),n}async function g(t,i,e){let n=await t.evaluate(async(r,s,a)=>await new Promise((o,l)=>{let u=setTimeout(()=>{l(new Error(`waitForEvent() timeout, eventName: ${s}`))},a);r.addEventListener(s,c=>{clearTimeout(u),o(window.puppeteerSerializeEvent(c))},{once:!0})}),e,i,m.defaultTimeout);return await t.waitForChanges(),n}var h=class{constructor(i){this.eventName=i;this.events=[];this._cursor=0;this._queuedHandler=[]}get length(){return this.events.length}get firstEvent(){return this.events.at(0)}get lastEvent(){return this.events.at(-1)}async next(){let i=this._cursor;this._cursor++;let e=this.events[i];if(e)return await Promise.resolve({done:!1,value:e});{let n,r=new Promise(s=>n=s);return this._queuedHandler.push(n),await r.then(()=>({done:!1,value:this.events[i]}))}}push(i){this.events.push(i);let e=this._queuedHandler.shift();e&&e()}};async function E(t,i,e,n){let r=t._e2eEventIds++;t._e2eEvents.set(r,{eventName:e,callback:n}),await i.evaluate((s,a,o)=>{s.addEventListener(o,l=>{window.puppeteerOnEvent(a,window.puppeteerSerializeEvent(l))})},r,e)}function Y(t,i,e){let n=t.get(i);n&&n.callback(e)}function Q(){let t=async()=>await new Promise(n=>{requestAnimationFrame(n)}),i=async()=>{let n=[],r=(s,a)=>{if(a!=null&&a.nodeType===1)for(let o of a.children)o.tagName.includes("-")&&typeof o.componentOnReady=="function"&&s.push(o.componentOnReady()),r(s,o)};return r(n,window.document.documentElement),await Promise.all(n).then(()=>{}).catch(s=>console.error(s))},e=async()=>await i().then(async()=>await t()).then(async()=>await i()).then(()=>{window.puppeteerAppLoaded=!0});window.puppeteerSerializeEventTarget=n=>n?n===window?{serializedWindow:!0}:n===document?{serializedDocument:!0}:"nodeType"in n&&n.nodeType!=null?{serializedElement:!0,nodeName:n.nodeName,nodeValue:n.nodeValue,nodeType:n.nodeType,tagName:n.tagName,className:n.className,id:n.id}:null:null,window.puppeteerSerializeEvent=n=>({bubbles:n.bubbles,cancelBubble:n.cancelBubble,cancelable:n.cancelable,composed:n.composed,currentTarget:window.puppeteerSerializeEventTarget(n.currentTarget),defaultPrevented:n.defaultPrevented,detail:"detail"in n?n.detail:void 0,eventPhase:n.eventPhase,isTrusted:n.isTrusted,returnValue:n.returnValue,srcElement:window.puppeteerSerializeEventTarget(n.srcElement),target:window.puppeteerSerializeEventTarget(n.target),timeStamp:n.timeStamp,type:n.type,isSerializedEvent:!0}),window.document.readyState==="complete"?e():document.addEventListener("readystatechange",()=>{document.readyState==="complete"&&e()})}var X=globalThis.HTMLElement??function(){},m=class t extends X{constructor(e=t._page,n=t._handle){super();this._page=e;this._handle=n;this._queuedActions=[];e._e2eElements.push(this)}static{this.defaultTimeout=2500}static create(e,n){customElements.get("e2e-element")||customElements.define("e2e-element",t),t._page=e,t._handle=n;let r=document.createElement("e2e-element");return t._page=void 0,t._handle=void 0,r}async find(e){return await y(this._page,this._handle,e)}async findAll(e){return await b(this._page,this._handle,e)}async callMethod(e,...n){return this._queuedActions.push({methodName:e,methodArgs:n}),await this.e2eRunActions()}triggerEvent(e,n){this._queuedActions.push({eventName:e,eventInitDict:n})}async spyOnEvent(e){let n=new h(e);return await E(this._page,this._handle,e,r=>{n.push(r)}),n}async click(e){await this._handle.click(e),await this._page.waitForChanges()}async focus(){await this._handle.focus(),await this._page.waitForChanges()}async hover(){await this._handle.hover(),await this._page.waitForChanges()}async isVisible(){this._validate();let e=!1;try{e=await this._handle.frame.evaluate(async r=>await new Promise(s=>{window.requestAnimationFrame(()=>{if(r.isConnected){let a=window.getComputedStyle(r);!!a&&a.display!=="none"&&a.visibility!=="hidden"&&a.opacity!=="0"?window.requestAnimationFrame(()=>{r.clientWidth,s(!0)}):s(!1)}else s(!1)})}),this._handle)}catch{}return e}async waitForEvent(e){return await g(this._page,e,this._handle)}async waitForVisible(){await this.awaitVisibility()}async waitForNotVisible(){await this.awaitVisibility(!1)}async awaitVisibility(e=!0){await new Promise((n,r)=>{let s=async()=>{let c=await this.isVisible();e===c&&(clearInterval(o),clearTimeout(u),n())},o=setInterval(()=>void s(),10),l=new Error(`waitForNotVisible timed out: ${t.defaultTimeout}ms`),u=setTimeout(()=>{clearTimeout(o),r(l)},t.defaultTimeout)})}async isIntersectingViewport(){return await this._handle.isIntersectingViewport()}async press(e,n){await this._handle.press(e,n),await this._page.waitForChanges()}async tap(){await this._handle.tap(),await this._page.waitForChanges()}async type(e,n){await this._handle.type(e,n),await this._page.waitForChanges()}async getProperty(e){return this._validate(),await this._handle.frame.evaluate((s,a)=>s[a],this._handle,e)}setProperty(e,n){this._queuedActions.push({setPropertyName:e,setPropertyValue:n})}getAttribute(e){return this._validate(),super.getAttribute(e)}setAttribute(e,n){super.setAttribute(e,n),this._queuedActions.push({setAttributeName:e,setAttributeValue:n})}removeAttribute(e){super.removeAttribute(e),this._queuedActions.push({removeAttribute:e})}toggleAttribute(e,n){let r=super.toggleAttribute(e,n);return this._queuedActions.push({toggleAttributeName:e,toggleAttributeForce:n}),r}get innerHTML(){return this._validate(),super.innerHTML}set innerHTML(e){this._queuedActions.push({setPropertyName:"innerHTML",setPropertyValue:e})}get innerText(){return this._validate(),super.innerText}set innerText(e){this._queuedActions.push({setPropertyName:"innerText",setPropertyValue:e})}get nodeValue(){return this._validate(),super.nodeValue}set nodeValue(e){typeof e=="string"&&this._queuedActions.push({setPropertyName:"nodeValue",setPropertyValue:e})}get outerHTML(){return this._validate(),super.outerHTML}set outerHTML(e){throw new Error("outerHTML is read-only")}get textContent(){return this._validate(),super.textContent}set textContent(e){super.textContent=e,this._queuedActions.push({setPropertyName:"textContent",setPropertyValue:e})}async getComputedStyle(e){let n=await this._page.evaluate((r,s)=>{let a={},o=window.getComputedStyle(r,s);return[...Object.keys(o),...Array.from(r.style??[])].forEach(u=>{if(isNaN(u)){let c=o[u]||o.getPropertyValue(u);c!=null&&(a[u]=c)}else{let c=String(o[u]);if(c.includes("-")){let v=o.getPropertyValue(c);v!=null&&(a[c]=v)}}}),a},this._handle,e);return n.getPropertyValue=r=>n[r],n}async e2eRunActions(){if(this._queuedActions.length===0)return;let n=await this._handle.frame.evaluate(async(r,s)=>await r.componentOnReady().then(()=>{let a;return s.forEach(o=>{if(o.methodName)a=r[o.methodName].apply(r,o.methodArgs??[]);else if(o.setPropertyName)r[o.setPropertyName]=o.setPropertyValue;else if(o.setAttributeName)r.setAttribute(o.setAttributeName,String(o.setAttributeValue));else if(o.removeAttribute)r.removeAttribute(o.removeAttribute);else if(o.toggleAttributeName)typeof o.toggleAttributeForce=="boolean"?r.toggleAttribute(o.toggleAttributeName,o.toggleAttributeForce):r.toggleAttribute(o.toggleAttributeName);else if(o.classAdd)r.classList.add(o.classAdd);else if(o.classRemove)r.classList.remove(o.classRemove);else if(o.classToggle)r.classList.toggle(o.classToggle);else if(o.eventName){let l=new CustomEvent(o.eventName,{bubbles:!0,cancelable:!0,composed:!0,...o.eventInitDict});r.dispatchEvent(l)}}),a}),this._handle,this._queuedActions);return this._queuedActions.length=0,n}async e2eSync(){let e=this._handle.frame,{outerHtml:n,shadowRootHtml:r}=await e.evaluate(o=>({outerHtml:o.outerHTML,shadowRootHtml:o.shadowRoot?.innerHTML??null}),this._handle);if(typeof r=="string"){this.shadowRoot||this.attachShadow({mode:"open"});let o=this._parseHtmlToFragment(r);this._modeChildren(o,this.shadowRoot)}let a=this._parseHtmlToFragment(n).firstElementChild;a&&(Object.defineProperty(this,"tagName",{value:a.tagName,configurable:!0}),Object.defineProperty(this,"nodeName",{value:a.nodeName,configurable:!0}),Array.from(this.attributes,o=>this.removeAttributeNode(o)),Array.from(a.attributes).forEach(o=>{super.setAttribute(o.name,o.value)}),this._modeChildren(a,this))}_modeChildren(e,n){for(;n.childNodes.length>0;)n.removeChild(n.childNodes[0]);for(;e.childNodes.length>0;)n.appendChild(e.childNodes[0])}_parseHtmlToFragment(e){let r=new DOMParser().parseFromString(e,"text/html"),s=document.createDocumentFragment();for(;r.body.firstChild;)s.appendChild(r.body.firstChild);return s}_validate(){if(this._queuedActions.length>0)throw new Error("await page.waitForChanges() must be called before reading element information");if(!this._handle)throw new Error("trying to read from a disposed element")}async e2eDispose(){this._handle&&(await this._handle.dispose(),this._handle=null);let e=this._page._e2eElements.indexOf(this);e>-1&&this._page._e2eElements.splice(e,1),this._page=null}cloneNode(e){let n=super.cloneNode(e);return Object.defineProperty(n,"tagName",{value:this.tagName,configurable:!0}),Object.defineProperty(n,"nodeName",{value:this.nodeName,configurable:!0}),n}};async function y(t,i,e){let{lightSelector:n,text:r,contains:s}=N(e);if(typeof e=="string"&&e.includes(">>>")){let l=await t.$(e);if(!l)return null;let u=m.create(t,l);return await u.e2eSync(),u}let a;if(typeof n=="string"?a=await i.$(n):a=await Z(t,i,r,s),!a)return null;let o=m.create(t,a);return await o.e2eSync(),o}async function Z(t,i,e,n){let r=await t.evaluateHandle((s,a,o)=>{let l=null;function u(c){if(!c||l)return;if(c.nodeType===3){if(typeof a=="string"&&c.textContent?.trim()===a){l=c.parentElement;return}if(typeof o=="string"&&c.textContent?.includes(o)){l=c.parentElement;return}}else{if(c.nodeName==="SCRIPT"||c.nodeName==="STYLE")return;u(c.shadowRoot),c.childNodes?.forEach(u)}}return u(s),l},i,e,n);return r?r.asElement():null}async function b(t,i,e){let n=[];if(typeof e=="string"&&e.includes(">>>")){let a=await t.$$(e);for(let o of a){let l=m.create(t,o);await l.e2eSync(),n.push(l)}return n}let{lightSelector:r}=N(e);if(r===void 0)return[];let s=await i.$$(r);if(s.length===0)return[];for(let a of s){let o=m.create(t,a);await o.e2eSync(),n.push(o)}return n}function N(t){let i={lightSelector:void 0,text:void 0,contains:void 0};if(typeof t=="string")i.lightSelector=t.trim();else if(typeof t.text=="string")i.text=t.text.trim();else if(typeof t.contains=="string")i.contains=t.contains.trim();else throw new Error(`invalid find selector: ${JSON.stringify(t)}`);return i}import{inject as ee}from"vitest";var d=new Proxy({},{get(t,i){return ee(i)},set(){throw new Error("Injected object is read-only")}});import{VitestTestRunner as te}from"vitest/runners";async function F(){return await(await import("puppeteer")).connect(d.puppeteerConnectOptions)}var x=globalThis,P=class extends te{constructor(...e){super(...e);this._browser=void 0;this._pages=[];x.runner=this,d.isDevToolsEnabled&&(this.config.testTimeout??5e3)===5e3&&(this.config.testTimeout=18e5)}async createNewPage(){this._browser??=await F(),this._pages.length>0&&await this.closeOpenPages();let e=await this._browser.newPage();return this._pages.push(e),e}async closeOpenPages(){await Promise.all(this._pages.filter(e=>!e.isClosed()).map(async e=>await e.close())),this._pages.length=0}async onAfterRunSuite(e){await Promise.all([super.onAfterRunSuite(e),this.closeOpenPages().then(async()=>await this._browser?.disconnect())])}};async function ne(t){let i=await x.runner.createNewPage();try{return await ie(i,t)}catch(e){throw i.isClosed()||await i.close(),e}}async function ie(t,i){let e=[];await t.setCacheEnabled(!1);let n={_e2eElements:[],_originalClose:t.close,_e2eEvents:new Map,_e2eEventIds:0,async spyOnEvent(...o){return await S.call(r,r,...o)},async close(o){try{if(Array.isArray(r._e2eElements)){let l=r._e2eElements.map(async u=>{typeof u.e2eDispose=="function"&&await u.e2eDispose()});await Promise.all(l)}}catch{}await Promise.all(f),re(r);try{r.isClosed()||await r._originalClose?.(o)}catch{}},async find(o){let l=await a();return await y(r,l,o)},async findAll(o){let l=await a();return await b(r,l,o)},async waitForEvent(o){let l=await a();return await g(r,o,l)},getDiagnostics:()=>e,async waitForChanges(){await ae(r)},async debugger(){if(!d.isDevToolsEnabled)throw new Error("Re-run test with the --inspect flag or set `puppeteerTesting.launchOptions.devtools: true` in order to use E2EPage.debugger()");d.isHeadlessBrowser&&console.warn("E2EPage.debugger() called while in headless mode. This may freeze the test."),await r.evaluate(async()=>await new Promise(o=>{debugger;o()}))},goTo:oe,setContent:A},r=Object.assign(t,n);await C(r);let s;async function a(){return s??=r.evaluateHandle(()=>document),(await s).asElement()}return r.on("console",o=>{o.type()==="error"&&e.push({type:"error",message:o.text(),location:o.location().url}),le(o)}),r.on("pageerror",o=>{throw e.push({type:"pageerror",message:o.message,location:o.stack}),o}),r.on("requestfailed",o=>{let l=o.url(),u=o.failure()?.errorText;e.push({type:"requestfailed",message:u,location:l}),console.error("Request failed",l,u)}),typeof i.html=="string"&&await A.call(r,i.html),r}function re(t){function i(){throw new Error("The page was already closed")}t.goto=i,t.find=i,t.debugger=i,t.findAll=i,t.setContent=i,t.spyOnEvent=i,t.waitForChanges=i,t.waitForEvent=i}async function oe(t,i={}){if(this.isClosed())throw new Error("e2eGoTo unavailable: page already closed");if(typeof t!="string")throw new Error("invalid gotoTest() url");if(!t.startsWith("/"))throw new Error("gotoTest() url must start with /");let e=d.devServerUrl;if(typeof e!="string")throw new Error("invalid gotoTest() browser url");let n=e+t.substring(1),r=await this.goto(n,i);if(r?.ok()!==!0)throw new Error(`Testing unable to load ${t}, HTTP status: ${String(r?.status())}`);return await M(this,i),r}async function A(t,i={}){if(this.isClosed())throw new Error("e2eSetContent unavailable: page already closed");if(typeof t!="string")throw new Error("invalid e2eSetContent() html");let e=d.devServerHtml;if(typeof e!="string")throw new Error("invalid e2eSetContent() app script url");let n=e.replace("<body>",`<body>
|
|
2
|
+
${t}`),r=d.devServerUrl;if(r===void 0)throw new Error("invalid e2eSetContent() browser url");if(await this.setRequestInterception(!0),this.on("request",a=>{r===a.url()?a.respond({status:200,contentType:"text/html",body:n}):a.continue()}),(await this.goto(r,i))?.ok()!==!0)throw new Error("Testing unable to load content");await M(this,i)}async function M(t,i){try{let e=i.timeout??se;await t.waitForFunction("window.puppeteerAppLoaded",{timeout:e})}catch(e){throw new Error(`App did not load in allowed time. Please ensure the content loads a web component application. Error: ${String(e)}`)}}var se=4750;async function ae(t){try{if(t.isClosed()||(await Promise.all(t._e2eElements.map(async e=>await e.e2eRunActions())),t.isClosed())||(await t.evaluate(async()=>await new Promise(e=>{requestAnimationFrame(()=>{let n=[],r=s=>{if(s!=null){"shadowRoot"in s&&s.shadowRoot instanceof ShadowRoot&&r(s.shadowRoot);let a=s.children,o=a.length;for(let l=0;l<o;l++){let u=a[l];u!=null&&(u.tagName?.includes("-")&&typeof u.componentOnReady=="function"&&n.push(u.componentOnReady()),r(u))}}};r(document.documentElement),Promise.all(n).finally(e)})})),t.isClosed()))return;let i=100;await new Promise(e=>setTimeout(e,i)),await Promise.all(t._e2eElements.map(async e=>await e.e2eSync()))}catch{}}var f=[];async function le(t){let i=t.type();if(i==="debug")return;let e=ue(t);f.push(e),await Promise.all(f.slice(0,-1));let n=await e;f.splice(f.indexOf(e),1),!n.startsWith("Using Calcite Components")&&(typeof console[i]=="function"?console[i](n):console.log(i,n))}async function ue(t){return[(await Promise.all(t.args().map(ce))).join(" "),`
|
|
3
|
+
Stack:
|
|
4
|
+
`,t.stackTrace().map(de).join(`
|
|
5
|
+
`),`
|
|
6
|
+
`].join("")}async function ce(t){let i=t.toString();if(i.startsWith(k))return i.slice(k.length);try{return await t.evaluate(e=>{if(typeof e=="object"&&e!==null){if(e instanceof Error)return String(e);if("tagName"in e&&"attributes"in e)return`<${e.tagName.toLowerCase()} ${Array.from(e.attributes,n=>`${n.name}="${n.value}"`).join(" ")}>`;try{let n=e?.constructor?.name;if(n)return`[${n} ${JSON.stringify(e)}]`}catch{}}return String(e)})}catch(e){return console.error(e),t.toString()}finally{t.dispose()}}var k="JSHandle:";function de(t){let i="";if(t?.url){let e=t.url.indexOf($);i=` ${e===-1?t.url:R(t.url.slice(e+$.length))}`,t.lineNumber&&(i+=`:${t.lineNumber}`),t.columnNumber&&(i+=`:${t.columnNumber}`)}return i}var $=_?"/@fs":"/@fs/";import{expect as me,afterEach as pe}from"vitest";function p(t,i){if(typeof t!="object"||t===null)throw new Error(`${i} expect called with non-element value`);if("then"in t&&typeof t.then=="function")throw new Error("element must be a resolved value, not a promise, before it can be tested");if(!("getAttribute"in t)||typeof t.getAttribute!="function")throw new Error(`expect ${i} value is not an element`)}var L=(t,i,e)=>{p(t,"toEqualAttribute");let n=t.getAttribute(i);e!=null&&(e=String(e)),n!=null&&(n=String(n));let r=e===n;return{message:()=>`expected attribute ${i} "${e}" to ${r?"not ":""}equal "${n}"`,pass:r}},O=(t,i)=>{p(t,"toEqualAttributes");let e=Object.keys(i),n=e.every(r=>{let s=i[r];return s!=null&&(s=String(s)),t.getAttribute(r)===s});return{message:()=>`expected attributes to ${n?"not ":""}equal ${e.map(r=>`[${r}="${String(i[r])}"]`).join(", ")}`,pass:n}},D=(t,i)=>{p(t,"toHaveAttribute");let e=t.hasAttribute(i);return{message:()=>`expected to ${e?"not ":""}have the attribute "${i}"`,pass:e}};var z=(t,i)=>{p(t,"toHaveClass");let e=t.classList.contains(i);return{message:()=>`expected to ${e?"not ":""}have css class "${i}"`,pass:e}},T=(t,i)=>{p(t,"toHaveClasses");let e=i.every(n=>t.classList.contains(n));return{message:()=>`expected to ${e?"not ":""}have css classes "${i.join(" ")}", but className is "${t.className}"`,pass:e}},V=(t,i)=>{p(t,"toMatchClasses");let{pass:e}=T(t,i);return e&&(e=i.length===t.classList.length),{message:()=>`expected to ${e?"not ":""}match css classes "${i.join(" ")}", but className is "${t.className}"`,pass:e}};var q=t=>{w(t);let i=t.events.length>0;return{message:()=>`expected to have ${i?"not ":""}called "${t.eventName}" event`,pass:i}};function w(t){if(typeof t!="object"||t===null)throw new Error(`expected to receive an event spy. got ${typeof t}`);if("then"in t&&typeof t.then=="function")throw new Error("event spy must be a resolved value, not a promise, before it can be tested");if(!("eventName"in t))throw new Error("toHaveReceivedEvent did not receive an event spy")}var j=(t,i)=>{w(t);let e=t.length===i;return{message:()=>`expected event "${t.eventName}" to have been called ${i} times, but was called ${t.events.length} time${t.events.length>1?"s":""}`,pass:e}},W=function(i,e){if(w(i),!i.lastEvent)throw new Error(`event "${i.eventName}" was not received`);let n=this.equals(i.lastEvent.detail,e);return expect(i.lastEvent.detail).toEqual(e),{message:()=>`expected event "${i.eventName}" detail to ${n?"not ":""}equal`,pass:n}},B=function(i,e){if(w(i),!i.firstEvent)throw new Error(`event "${i.eventName}" was not received`);let n=this.equals(i.firstEvent.detail,e);return expect(i.firstEvent.detail).toEqual(e),{message:()=>`expected event "${i.eventName}" detail to ${n?"not ":""}equal`,pass:n}},I=function(i,e){if(w(i),!i.firstEvent)throw new Error(`event "${i.eventName}" was not received`);let n=this.equals(i.lastEvent?.detail,e);return expect(i.lastEvent?.detail).toEqual(e),{message:()=>`expected event "${i.eventName}" detail to ${n?"not ":""}equal`,pass:n}},J=function(i,e,n){if(w(i),!i.firstEvent)throw new Error(`event "${i.eventName}" was not received`);let r=i.events[e];if(!r)throw new Error(`event at index ${e} was not received`);let s=this.equals(r.detail,n);return expect(r.detail).toEqual(n),{message:()=>`expected event "${i.eventName}" detail to ${s?"not ":""}equal`,pass:s}};var U=(t,i)=>{if(t==null)throw new Error("toEqualText expect called with nullish value");if(typeof t=="object"&&"then"in t&&typeof t.then=="function")throw new Error("element must be a resolved value, not a promise, before it can be tested");let e;typeof t=="object"&&"textContent"in t&&typeof t.textContent=="string"?e=(t.textContent??"").replace(H," ").trim():e=String(t).replace(H," ").trim(),i=String(i).replace(H," ").trim();let n=e===i;return{message:()=>`expected textContent "${i}" to ${n?"not ":""}equal "${e}"`,pass:n}},H=/\s+/gu;var G={toEqualAttribute:L,toEqualAttributes:O,toEqualText:U,toHaveAttribute:D,toHaveClass:z,toHaveClasses:T,toMatchClasses:V,toHaveReceivedEvent:q,toHaveReceivedEventTimes:j,toHaveReceivedEventDetail:W,toHaveFirstReceivedEventDetail:B,toHaveLastReceivedEventDetail:I,toHaveNthReceivedEventDetail:J};function we(){me.extend(G),pe(()=>{document.body.childNodes.forEach(K)})}function K(t){t.childNodes.forEach(K),t.remove()}export{P as default,ne as newE2EPage,we as setupPuppeteerTest};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { ClickOptions, ElementHandle, KeyInput } from "puppeteer";
|
|
2
|
+
import { EventSpy } from "./events";
|
|
3
|
+
import type { E2EPage, FindSelector, SerializedEvent } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* This file is part of the puppeteer-testing bundle. That bundle may be
|
|
6
|
+
* imported even before happy-dom is setup.
|
|
7
|
+
*/
|
|
8
|
+
declare const Superclass: {
|
|
9
|
+
new (): HTMLElement;
|
|
10
|
+
prototype: HTMLElement;
|
|
11
|
+
};
|
|
12
|
+
export declare class E2EElement extends Superclass {
|
|
13
|
+
private _page;
|
|
14
|
+
private _handle;
|
|
15
|
+
/**
|
|
16
|
+
* The '2500' value that we default to is the value of `jasmine.DEFAULT_TIMEOUT_INTERVAL` (5000) divided by 2.
|
|
17
|
+
*/
|
|
18
|
+
static defaultTimeout: number;
|
|
19
|
+
private static _page;
|
|
20
|
+
private static _handle;
|
|
21
|
+
/**
|
|
22
|
+
* We can't directly call `new E22Element()` since it extends HTMLElement
|
|
23
|
+
* which is not directly constructable. Instead, we register it as a custom
|
|
24
|
+
* element.
|
|
25
|
+
*/
|
|
26
|
+
static create(page: E2EPage, handle: ElementHandle): E2EElement;
|
|
27
|
+
private _queuedActions;
|
|
28
|
+
constructor(_page?: E2EPage, _handle?: ElementHandle);
|
|
29
|
+
/**
|
|
30
|
+
* Find a child element that matches the selector, which is the same as
|
|
31
|
+
* `element.querySelector(selector)`. Use `>>>` within the
|
|
32
|
+
* selector to find an element within a host element's shadow root.
|
|
33
|
+
* For example, to select the first `div` inside of the component
|
|
34
|
+
* `my-cmp`, which is a child of this element, the call would be
|
|
35
|
+
* `element.find('my-cmp >>> div')`. Returns `null` if no
|
|
36
|
+
* elements were found.
|
|
37
|
+
*/
|
|
38
|
+
find(selector: FindSelector): Promise<E2EElement>;
|
|
39
|
+
/**
|
|
40
|
+
* Find all child elements that match the selector, which is the same as
|
|
41
|
+
* `element.querySelectorAll(selector)`. Use `>>>` within the
|
|
42
|
+
* selector to find elements within a host element's shadow root.
|
|
43
|
+
* For example, to select all `li` elements inside of the component
|
|
44
|
+
* `my-cmp`, which is a child of this element, the call would be
|
|
45
|
+
* `element.findAll('my-cmp >>> li')`. Returns an empty array if
|
|
46
|
+
* no elements were found.
|
|
47
|
+
*/
|
|
48
|
+
findAll(selector: FindSelector): Promise<E2EElement[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Used to call a method on a component. For example, if a component
|
|
51
|
+
* has the method `cmp.myMethod(arg1, arg2)`, calling this method
|
|
52
|
+
* from a e2e test could be `cmp.callMethod('myMethod', arg1, arg2)`.
|
|
53
|
+
*/
|
|
54
|
+
callMethod(methodName: string, ...methodArgs: unknown[]): Promise<unknown>;
|
|
55
|
+
/**
|
|
56
|
+
* This is a convenience method to easily create a `CustomEvent`,
|
|
57
|
+
* and dispatch it from the element, to include any custom event
|
|
58
|
+
* `detail` data as the second argument.
|
|
59
|
+
*/
|
|
60
|
+
triggerEvent(eventName: string, eventInitDict?: EventInit): void;
|
|
61
|
+
/**
|
|
62
|
+
* Used to test if an event was, or was not dispatched. This method
|
|
63
|
+
* returns a promise, that resolves with an EventSpy. The EventSpy
|
|
64
|
+
* can be used along with `expect(spy).toHaveReceivedEvent()`,
|
|
65
|
+
* `expect(spy).toHaveReceivedEventTimes(x)` and
|
|
66
|
+
* `expect(spy).toHaveReceivedEventDetail({...})`.
|
|
67
|
+
*/
|
|
68
|
+
spyOnEvent(eventName: string): Promise<EventSpy>;
|
|
69
|
+
/**
|
|
70
|
+
* Calling `click()` on an element scrolls it into view if needed, and
|
|
71
|
+
* then uses `page.mouse` to click in the center of the element.
|
|
72
|
+
* Please see the puppeteer docs for more information.
|
|
73
|
+
*/
|
|
74
|
+
click(options?: ClickOptions): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Sets focus on the element.
|
|
77
|
+
*/
|
|
78
|
+
focus(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Sets hover on the element.
|
|
81
|
+
*/
|
|
82
|
+
hover(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Resolves `true` when the element's style is `display !== 'none'`,
|
|
85
|
+
* `visibility !== 'hidden'` and `opacity !== '0'`.
|
|
86
|
+
*/
|
|
87
|
+
isVisible(): Promise<boolean>;
|
|
88
|
+
/**
|
|
89
|
+
* Waits until the given event is listened in the element.
|
|
90
|
+
*/
|
|
91
|
+
waitForEvent(eventName: string): Promise<SerializedEvent>;
|
|
92
|
+
/**
|
|
93
|
+
* Waits until the element's style is `display !== 'none'`,
|
|
94
|
+
* `visibility !== 'hidden'`, `opacity !== '0'` and the element
|
|
95
|
+
* is connected to the document.
|
|
96
|
+
*/
|
|
97
|
+
waitForVisible(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Waits until the element's style is `display === 'none'`, or
|
|
100
|
+
* `visibility === 'hidden'`, or `opacity === '0'`, or the element
|
|
101
|
+
* is no longer connected to the document.
|
|
102
|
+
*/
|
|
103
|
+
waitForNotVisible(): Promise<void>;
|
|
104
|
+
awaitVisibility(waitForVisible?: boolean): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Resolves to true if the element is visible in the current viewport.
|
|
107
|
+
*/
|
|
108
|
+
isIntersectingViewport(): Promise<boolean>;
|
|
109
|
+
/**
|
|
110
|
+
* Focuses the element, and then uses `keyboard.down` and `keyboard.up`.
|
|
111
|
+
* If key is a single character and no modifier keys besides Shift are
|
|
112
|
+
* being held down, a keypress/input event will also be generated. The
|
|
113
|
+
* text option can be specified to force an input event to be generated.
|
|
114
|
+
* Note: Modifier keys DO effect `elementHandle.press`. Holding down Shift
|
|
115
|
+
* will type the text in upper case.
|
|
116
|
+
* Key names: https://github.com/puppeteer/puppeteer/blob/main/src/common/USKeyboardLayout.ts
|
|
117
|
+
*/
|
|
118
|
+
press(key: KeyInput, options?: {
|
|
119
|
+
text?: string;
|
|
120
|
+
delay?: number;
|
|
121
|
+
}): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* This method scrolls the element it into view if needed,
|
|
124
|
+
* and then uses `page.touchscreen` to tap in the center of the element.
|
|
125
|
+
*/
|
|
126
|
+
tap(): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Sends a keydown, keypress/input, and keyup event for each character in the text.
|
|
129
|
+
* To press a special key, like Control or ArrowDown, use `keyboard.press`.
|
|
130
|
+
*/
|
|
131
|
+
type(text: string, options?: {
|
|
132
|
+
delay: number;
|
|
133
|
+
}): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Returns the value of a specified attribute on the element. If the
|
|
136
|
+
* given attribute does not exist, the value returned will be null.
|
|
137
|
+
*/
|
|
138
|
+
getProperty<T = any>(propertyName: string): Promise<T>;
|
|
139
|
+
/**
|
|
140
|
+
* Used to set a property set on a component. For example, if a
|
|
141
|
+
* component has the property `elm.myProp`, then calling
|
|
142
|
+
* `elm.setProperty('myProp', 88)` would set the value `88` to
|
|
143
|
+
* the `myProp` property on the component.
|
|
144
|
+
*/
|
|
145
|
+
setProperty(propertyName: string, value: unknown): void;
|
|
146
|
+
/**
|
|
147
|
+
* Returns the value of a specified attribute on the element. If the
|
|
148
|
+
* given attribute does not exist, the value returned will be null.
|
|
149
|
+
*/
|
|
150
|
+
getAttribute(name: string): string | null;
|
|
151
|
+
/**
|
|
152
|
+
* Removes the attribute on the specified element. Note that
|
|
153
|
+
* `await page.waitForChanges()` must be called before reading
|
|
154
|
+
* the value if content has changed.
|
|
155
|
+
*/
|
|
156
|
+
setAttribute(name: string, value: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Removes the attribute on the specified element. Note that
|
|
159
|
+
* `await page.waitForChanges()` must be called before reading
|
|
160
|
+
* the value if content has changed.
|
|
161
|
+
*/
|
|
162
|
+
removeAttribute(name: string): void;
|
|
163
|
+
/**
|
|
164
|
+
* Toggles a `boolean` attribute (removing it if it is present and adding
|
|
165
|
+
* it if it is not present) on the given element. Note that
|
|
166
|
+
* `await page.waitForChanges()` must be called before reading
|
|
167
|
+
* the value if content has changed. The optional `force` argument is a
|
|
168
|
+
* `boolean` value to determine whether the attribute should be added or
|
|
169
|
+
* removed, no matter whether the attribute is present or not at the moment.
|
|
170
|
+
*/
|
|
171
|
+
toggleAttribute(name: string, force?: boolean): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Gets and sets `innerHTML` property of the element.
|
|
174
|
+
* Note that `await page.waitForChanges()` must be called before reading
|
|
175
|
+
* the value if content has changed.
|
|
176
|
+
*/
|
|
177
|
+
get innerHTML(): string;
|
|
178
|
+
set innerHTML(value: string);
|
|
179
|
+
/**
|
|
180
|
+
* Gets and sets `innerText` property of the element.
|
|
181
|
+
* Note that `await page.waitForChanges()` must be called before reading
|
|
182
|
+
* the value if content has changed.
|
|
183
|
+
*/
|
|
184
|
+
get innerText(): string;
|
|
185
|
+
set innerText(value: string);
|
|
186
|
+
get nodeValue(): string | null;
|
|
187
|
+
set nodeValue(value: string);
|
|
188
|
+
/**
|
|
189
|
+
* Gets the element's `outerHTML. This is a read-only property and will
|
|
190
|
+
* throw an error if set.
|
|
191
|
+
*/
|
|
192
|
+
get outerHTML(): string;
|
|
193
|
+
set outerHTML(_: never);
|
|
194
|
+
/**
|
|
195
|
+
* The `textContent` property represents the text content of a node
|
|
196
|
+
* and its descendants. Note that `await page.waitForChanges()` must
|
|
197
|
+
* be called before reading the value if content has changed.
|
|
198
|
+
*/
|
|
199
|
+
get textContent(): string;
|
|
200
|
+
set textContent(value: string);
|
|
201
|
+
/**
|
|
202
|
+
* Returns an object that reports the values of all CSS properties of this
|
|
203
|
+
* element after applying active stylesheets and resolving any basic computation
|
|
204
|
+
* those values may contain. Individual CSS property values are accessed by
|
|
205
|
+
* simply indexing with CSS property names. The method is shortcut and an async
|
|
206
|
+
* version of using `window.getComputedStyle(element)` directly.
|
|
207
|
+
*/
|
|
208
|
+
getComputedStyle(pseudoElement?: string | null): Promise<CSSStyleDeclaration>;
|
|
209
|
+
e2eRunActions(): Promise<unknown>;
|
|
210
|
+
e2eSync(): Promise<void>;
|
|
211
|
+
private _modeChildren;
|
|
212
|
+
private _parseHtmlToFragment;
|
|
213
|
+
private _validate;
|
|
214
|
+
e2eDispose(): Promise<void>;
|
|
215
|
+
cloneNode(deep?: boolean | undefined): Node;
|
|
216
|
+
}
|
|
217
|
+
export declare function find(page: E2EPage, rootHandle: ElementHandle, selector: FindSelector): Promise<E2EElement | null>;
|
|
218
|
+
export declare function findAll(page: E2EPage, rootHandle: ElementHandle, selector: FindSelector): Promise<E2EElement[]>;
|
|
219
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ElementHandle, JSHandle } from "puppeteer";
|
|
2
|
+
import type { E2EPage, SerializedEvent } from "./types";
|
|
3
|
+
export declare function initPageEvents(page: E2EPage): Promise<void>;
|
|
4
|
+
export declare function pageSpyOnEvent(page: E2EPage, eventName: string, selector?: "document" | "window"): Promise<EventSpy>;
|
|
5
|
+
export declare function waitForEvent(page: E2EPage, eventName: string, elementHandle: ElementHandle): Promise<SerializedEvent>;
|
|
6
|
+
export declare class EventSpy {
|
|
7
|
+
eventName: string;
|
|
8
|
+
events: SerializedEvent[];
|
|
9
|
+
private _cursor;
|
|
10
|
+
private _queuedHandler;
|
|
11
|
+
constructor(eventName: string);
|
|
12
|
+
get length(): number;
|
|
13
|
+
get firstEvent(): SerializedEvent | undefined;
|
|
14
|
+
get lastEvent(): SerializedEvent | undefined;
|
|
15
|
+
next(): Promise<{
|
|
16
|
+
done: boolean;
|
|
17
|
+
value: SerializedEvent | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
push(event: SerializedEvent): void;
|
|
20
|
+
}
|
|
21
|
+
export declare function addE2EListener(page: E2EPage, elementHandle: JSHandle, eventName: string, callback: (event: SerializedEvent) => void): Promise<void>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { HTTPResponse, Page, WaitForOptions } from "puppeteer";
|
|
2
|
+
import type { EventSpy } from "./events";
|
|
3
|
+
import type { E2EElement } from "./element";
|
|
4
|
+
export interface PageDiagnostic {
|
|
5
|
+
type: "error" | "pageerror" | "requestfailed";
|
|
6
|
+
message?: string;
|
|
7
|
+
location?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The E2EPage is a wrapper utility to Puppeteer in order to
|
|
11
|
+
* to create easier to write and read end-to-end tests.
|
|
12
|
+
*/
|
|
13
|
+
export interface E2EPage extends Page {
|
|
14
|
+
/**
|
|
15
|
+
* Sets a debugger;
|
|
16
|
+
*/
|
|
17
|
+
debugger: () => Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Find an element that matches the selector, which is the same as
|
|
20
|
+
* `document.querySelector(selector)`. Use `>>>` within the
|
|
21
|
+
* selector to find an element within the host element's shadow root.
|
|
22
|
+
* For example, to select the first `div` inside of the component
|
|
23
|
+
* `my-cmp`, the call would be `page.find('my-cmp >>> div')`.
|
|
24
|
+
* Returns `null` if an element was not found.
|
|
25
|
+
*/
|
|
26
|
+
find: (selector: FindSelector) => Promise<E2EElement>;
|
|
27
|
+
/**
|
|
28
|
+
* Find all elements that match the selector, which is the same as
|
|
29
|
+
* `document.querySelectorAll(selector)`. Use `>>>` within the
|
|
30
|
+
* selector to find elements within the host element's shadow root.
|
|
31
|
+
* For example, to select all of the `li` elements inside of the component
|
|
32
|
+
* `my-cmp`, the call would be `page.findAll('my-cmp >>> li')`.
|
|
33
|
+
* Returns an empty array if no elements were found.
|
|
34
|
+
*/
|
|
35
|
+
findAll: (selector: string) => Promise<E2EElement[]>;
|
|
36
|
+
/**
|
|
37
|
+
* During an end-to-end test, a dev-server is started so `page.goto(url)` can be used
|
|
38
|
+
* on the app being tested. Urls are always relative since the dev server provides
|
|
39
|
+
* a localhost address. A shortcut to `page.goto(url)` is to set the `url` option
|
|
40
|
+
* when creating a new page, such as `const page = await newE2EPage({ url })`.
|
|
41
|
+
*/
|
|
42
|
+
goTo: (url: string, options?: WaitForOptions) => Promise<HTTPResponse | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Instead of testing a url directly, html content can be mocked using
|
|
45
|
+
* `page.setContent(html)`. A shortcut to `page.setContent(html)` is to set
|
|
46
|
+
* the `html` option when creating a new page, such as
|
|
47
|
+
* `const page = await newE2EPage({ html })`.
|
|
48
|
+
*/
|
|
49
|
+
setContent: (html: string, options?: WaitForOptions) => Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Used to test if an event was, or was not dispatched. This method
|
|
52
|
+
* returns a promise, that resolves with an EventSpy. The EventSpy
|
|
53
|
+
* can be used along with `expect(spy).toHaveReceivedEvent()`,
|
|
54
|
+
* `expect(spy).toHaveReceivedEventTimes(x)` and
|
|
55
|
+
* `expect(spy).toHaveReceivedEventDetail({...})`.
|
|
56
|
+
*/
|
|
57
|
+
spyOnEvent: (eventName: string, selector?: "document" | "window") => Promise<EventSpy>;
|
|
58
|
+
/**
|
|
59
|
+
* Puppeteer has asynchronous architecture. Since all calls are async, it's
|
|
60
|
+
* required that `await page.waitForChanges()` is called when changes are
|
|
61
|
+
* made to components.
|
|
62
|
+
* An error will be thrown if changes were made to a component but
|
|
63
|
+
* `waitForChanges()` was not called.
|
|
64
|
+
*/
|
|
65
|
+
waitForChanges: () => Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Waits for the event to be received on `window`. The optional second argument
|
|
68
|
+
* allows the listener to be set to `document` if needed.
|
|
69
|
+
*/
|
|
70
|
+
waitForEvent: (eventName: string) => Promise<SerializedEvent>;
|
|
71
|
+
getDiagnostics: () => PageDiagnostic[];
|
|
72
|
+
isClosed: () => boolean;
|
|
73
|
+
/** @internal */
|
|
74
|
+
_e2eElements: E2EElement[];
|
|
75
|
+
/** @internal */
|
|
76
|
+
_e2eEvents: Map<number, WaitForEvent>;
|
|
77
|
+
/** @internal */
|
|
78
|
+
_e2eEventIds: number;
|
|
79
|
+
/** @internal */
|
|
80
|
+
_originalClose: Page["close"];
|
|
81
|
+
}
|
|
82
|
+
export interface SerializedEvent<Detail = unknown> {
|
|
83
|
+
bubbles: boolean;
|
|
84
|
+
cancelBubble: boolean;
|
|
85
|
+
cancelable: boolean;
|
|
86
|
+
composed: boolean;
|
|
87
|
+
currentTarget: SerializedElement;
|
|
88
|
+
defaultPrevented: boolean;
|
|
89
|
+
detail: Detail;
|
|
90
|
+
eventPhase: number;
|
|
91
|
+
isTrusted: boolean;
|
|
92
|
+
returnValue: boolean;
|
|
93
|
+
srcElement: SerializedElement;
|
|
94
|
+
target: SerializedElement;
|
|
95
|
+
timeStamp: number;
|
|
96
|
+
type: string;
|
|
97
|
+
isSerializedEvent: boolean;
|
|
98
|
+
}
|
|
99
|
+
export type SerializedElement = Record<string, unknown> | null;
|
|
100
|
+
export type FindSelector = FindSelectorOptions | string;
|
|
101
|
+
export interface FindSelectorOptions {
|
|
102
|
+
/**
|
|
103
|
+
* Finds an element with text content matching this
|
|
104
|
+
* exact value after the whitespace has been trimmed.
|
|
105
|
+
*/
|
|
106
|
+
text?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Finds an element with text content containing this value.
|
|
109
|
+
*/
|
|
110
|
+
contains?: string;
|
|
111
|
+
}
|
|
112
|
+
export interface WaitForEventOptions {
|
|
113
|
+
timeout?: number;
|
|
114
|
+
}
|
|
115
|
+
export interface WaitForEvent {
|
|
116
|
+
eventName: string;
|
|
117
|
+
callback: (event: SerializedEvent) => void;
|
|
118
|
+
}
|
|
119
|
+
export interface BrowserWindow extends Window {
|
|
120
|
+
puppeteerOnEvent: (id: number, event: SerializedEvent) => void;
|
|
121
|
+
puppeteerSerializeEvent: (event: CustomEvent | Event) => SerializedEvent;
|
|
122
|
+
puppeteerSerializeEventTarget: (target: Element | EventTarget | null) => SerializedElement;
|
|
123
|
+
puppeteerAppLoaded: boolean;
|
|
124
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RawMatcherFn, SyncExpectationResult } from "@vitest/expect";
|
|
2
|
+
export declare const toHaveClass: RawMatcherFn;
|
|
3
|
+
export declare const toHaveClasses: (element: unknown, expectClassNames: string[]) => SyncExpectationResult;
|
|
4
|
+
export declare const toMatchClasses: RawMatcherFn;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RawMatcherFn } from "@vitest/expect";
|
|
2
|
+
export declare const toHaveReceivedEvent: RawMatcherFn;
|
|
3
|
+
export declare const toHaveReceivedEventTimes: RawMatcherFn;
|
|
4
|
+
export declare const toHaveReceivedEventDetail: RawMatcherFn;
|
|
5
|
+
export declare const toHaveFirstReceivedEventDetail: RawMatcherFn;
|
|
6
|
+
export declare const toHaveLastReceivedEventDetail: RawMatcherFn;
|
|
7
|
+
export declare const toHaveNthReceivedEventDetail: RawMatcherFn;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare const expectExtend: {
|
|
2
|
+
toEqualAttribute: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
3
|
+
toEqualAttributes: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
4
|
+
toEqualText: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
5
|
+
toHaveAttribute: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
6
|
+
toHaveClass: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
7
|
+
toHaveClasses: (element: unknown, expectClassNames: string[]) => import("@vitest/expect").SyncExpectationResult;
|
|
8
|
+
toMatchClasses: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
9
|
+
toHaveReceivedEvent: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
10
|
+
toHaveReceivedEventTimes: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
11
|
+
toHaveReceivedEventDetail: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
12
|
+
toHaveFirstReceivedEventDetail: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
13
|
+
toHaveLastReceivedEventDetail: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
14
|
+
toHaveNthReceivedEventDetail: import("@vitest/expect").RawMatcherFn<import("@vitest/expect").MatcherState>;
|
|
15
|
+
};
|
|
16
|
+
interface PuppeteerMatchers<R> {
|
|
17
|
+
toEqualAttribute: (expectedAttribute: string, expectedValue: string) => R;
|
|
18
|
+
toEqualAttributes: (expectedAttributes: Record<string, unknown>) => R;
|
|
19
|
+
toEqualHtml: (expectedHtml: string) => R;
|
|
20
|
+
toEqualLightHtml: (expectedHtml: string) => R;
|
|
21
|
+
toEqualText: (expectedTextContent: string) => R;
|
|
22
|
+
toHaveAttribute: (expectedAttributeName: string) => R;
|
|
23
|
+
toHaveClass: (classNames: string) => R;
|
|
24
|
+
toHaveClasses: (classNames: string[]) => R;
|
|
25
|
+
toHaveReceivedEvent: () => R;
|
|
26
|
+
toHaveReceivedEventTimes: (count: number) => R;
|
|
27
|
+
toHaveReceivedEventDetail: (eventDetail: unknown) => R;
|
|
28
|
+
toHaveFirstReceivedEventDetail: (eventDetail: unknown) => R;
|
|
29
|
+
toHaveLastReceivedEventDetail: (eventDetail: unknown) => R;
|
|
30
|
+
toHaveNthReceivedEventDetail: (index: number, eventDetail: unknown) => R;
|
|
31
|
+
}
|
|
32
|
+
declare module "vitest" {
|
|
33
|
+
interface Assertion<T = any> extends PuppeteerMatchers<T> {
|
|
34
|
+
}
|
|
35
|
+
interface AsymmetricMatchersContaining extends PuppeteerMatchers<unknown> {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function assertIsElement(element: unknown, matcherName: string): asserts element is Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VitestTestRunner } from "vitest/runners";
|
|
2
|
+
import type { Page } from "puppeteer";
|
|
3
|
+
import type { Suite } from "@vitest/runner";
|
|
4
|
+
export type PuppeteerGlobalThis = typeof globalThis & {
|
|
5
|
+
runner: PuppeteerTestRunner;
|
|
6
|
+
};
|
|
7
|
+
export declare const puppeteerGlobalThis: PuppeteerGlobalThis;
|
|
8
|
+
export declare class PuppeteerTestRunner extends VitestTestRunner {
|
|
9
|
+
private _browser?;
|
|
10
|
+
private _pages;
|
|
11
|
+
constructor(...rest: ConstructorParameters<typeof VitestTestRunner>);
|
|
12
|
+
createNewPage(): Promise<Page>;
|
|
13
|
+
closeOpenPages(): Promise<void>;
|
|
14
|
+
onAfterRunSuite(suite: Suite): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupPuppeteerTest(): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unlike most of lumina-compiler code, this entrypoint may be executed in the
|
|
3
|
+
* browser (or in node.js), depending on where the tests are running.
|
|
4
|
+
*
|
|
5
|
+
* Thus, make sure to not import anything from the rest of the lumina-compiler
|
|
6
|
+
* in this bundle.
|
|
7
|
+
*/
|
|
8
|
+
export type { RenderOptions, RenderResult } from "./mount";
|
|
9
|
+
export { mount } from "./mount";
|
|
10
|
+
export { setupLuminaTest } from "./setupFile";
|
|
11
|
+
export { wrapController } from "./wrapController";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../chunk-JFKSI6I7.js";import{render as y}from"lit-html";import{html as g,unsafeStatic as d}from"lit-html/static.js";import{camelToKebab as v}from"@arcgis/components-utils";import{afterEach as b}from"vitest";async function M(e,{parent:t=document.body,afterConnect:n,dynamicComponents:o,cleanupAfterTest:s=!0}={}){let r=document.createElement("div");r.style.display="contents",t.append(r),s&&E.add(t),C(e);let l=o?.some(C),a;if(typeof e=="string")a=g`<${d(e)}></${d(e)}>`;else if(typeof e=="function")a="tagName"in e?g`<${d(e.tagName)}></${d(e.tagName)}>`:e();else{if(l)throw new Error('When rendering a dynamically created custom element using Lit\'s html`` function, you must ensure that the custom element class name is unique in the test file, or the class should explicitly have the `static override tagName = "some-tag-name";` property with a unique tag name within the test file');a=e}let i=[];function T(u){i.push(u.error),u.preventDefault(),u.stopPropagation()}if(window.addEventListener("error",T),y(a,r),window.removeEventListener("error",T),i.length===1)throw i[0];if(i.length>1)throw new AggregateError(i,"Multiple errors occurred while creating the custom element");let m=R(r),N=f,h=n?.(m);h?.then&&await h;let p=m;typeof p?.componentOnReady=="function"&&await p.componentOnReady();let c=p?._litComponent??N??m;return{el:m,component:c,async reRender(){return typeof e=="function"&&!("tagName"in e)&&y(e(),t),c.requestUpdate(),await c.updateComplete}}}var f,H=globalThis;H.devOnly$luminaComponentRefCallback=e=>{f=e};var E=new Set;b(()=>{E.forEach(O)});function O(e){for(;e.firstChild;)e.removeChild(e.firstChild);e._$litPart$=void 0}function C(e){if(!S(e)||e.runtime)return!1;let t=!1,n=e.tagName;if(!n){t=!1;let o=v(e.name.replaceAll(P,"")||"Test"),s=o==="test"?"te-st":o.includes("-")?o:`${o}-`;n=s;for(let r=2,l=customElements.get(n);l!==e&&l!==void 0;r+=1)t=!0,n=`${s}-${r}`,l=customElements.get(n)}return globalThis.devOnly$luminaRuntime?.customElement(n,e),t}var S=e=>typeof e=="function"&&"lumina"in e,P=/\d+$/gu;function R(e){for(let t of e.children)if("lumina"in t.constructor)return t;for(let t of e.children){let n=R(t);if(n!=null)return n}return e.firstElementChild??f?.el}import D from"vitest-fail-on-console";import{expect as $}from"vitest";import{html as _}from"js-beautify";function L(){$.addSnapshotSerializer({test(e){return typeof e=="object"&&e!==null&&"innerHTML"in e&&"onslotchange"in e},serialize(e){let t=e.innerHTML.replaceAll(k,"");return _(t,{indent_size:2,indent_char:" ",preserve_newlines:!1,wrap_line_length:70,indent_inner_html:!1,indent_empty_lines:!1})}})}var k=/<!--\??(?:lit\$\d+\$)?-->/gu;function J(){if(x[w])return;x[w]=!0;let e={...console};D({silenceMessage(t,n){return t.startsWith("Multiple versions of Lit loaded.")?!0:(e[n](t),!1)}}),L()}var w=Symbol.for("lumina:didSetupTest"),x=globalThis;import{toFunction as F}from"@arcgis/components-controllers";import{LitElement as z}from"@arcgis/lumina";function A(e,t){class n extends z{constructor(){super();let s="prototype"in e?F(e):e;this.controller=s(this),Promise.resolve(t?.(this)).catch(console.error)}render(){return String(typeof this.controller=="object"&&this.controller!==null&&"exports"in this.controller?this.controller.exports:this.controller)}}return n}export{M as mount,J as setupLuminaTest,A as wrapController};
|