@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.
Files changed (142) hide show
  1. package/LICENSE.md +13 -0
  2. package/README.md +21 -0
  3. package/dist/chunk-BQ4U6HQL.js +1 -0
  4. package/dist/chunk-JFKSI6I7.js +1 -0
  5. package/dist/context/index.d.ts +241 -0
  6. package/dist/context/types.d.ts +34 -0
  7. package/dist/context/utils.d.ts +23 -0
  8. package/dist/context/utils.spec.d.ts +1 -0
  9. package/dist/defaultAssetsUrl.d.ts +21 -0
  10. package/dist/defaultAssetsUrl.spec.d.ts +1 -0
  11. package/dist/dependencies/arcgisCore.d.ts +30 -0
  12. package/dist/dependencies/discover.d.ts +62 -0
  13. package/dist/dependencies/index.d.ts +11 -0
  14. package/dist/dependencies/lit.d.ts +2 -0
  15. package/dist/dependencies/loaders.d.ts +8 -0
  16. package/dist/dependencies/stencil.d.ts +6 -0
  17. package/dist/dependencies/testSetupFiles.d.ts +21 -0
  18. package/dist/dependencies/updateLumina.d.ts +8 -0
  19. package/dist/dependencies/updateLumina.spec.d.ts +1 -0
  20. package/dist/dependencies/utils.d.ts +23 -0
  21. package/dist/entrypoints/addNonLazyImports.d.ts +13 -0
  22. package/dist/entrypoints/config.d.ts +23 -0
  23. package/dist/entrypoints/dtsUtils.d.ts +22 -0
  24. package/dist/entrypoints/dtsUtils.spec.d.ts +1 -0
  25. package/dist/entrypoints/findUtils.d.ts +21 -0
  26. package/dist/entrypoints/findUtils.spec.d.ts +1 -0
  27. package/dist/entrypoints/handleComponentImports.d.ts +13 -0
  28. package/dist/entrypoints/pathMapping.d.ts +25 -0
  29. package/dist/entrypoints/resolveTagName.d.ts +14 -0
  30. package/dist/entrypoints/resolveTagName.spec.d.ts +1 -0
  31. package/dist/frameworkTypes/index.d.ts +15 -0
  32. package/dist/frameworkTypes/lumina.d.ts +5 -0
  33. package/dist/frameworkTypes/preact.d.ts +6 -0
  34. package/dist/frameworkTypes/react.d.ts +6 -0
  35. package/dist/frameworkTypes/stencil.d.ts +5 -0
  36. package/dist/frameworkTypes/utils.d.ts +8 -0
  37. package/dist/frameworkTypes/vanilla.d.ts +3 -0
  38. package/dist/index.d.ts +29 -0
  39. package/dist/index.js +248 -0
  40. package/dist/jsxToLitHtml/autoAddNothing.d.ts +8 -0
  41. package/dist/jsxToLitHtml/comments.d.ts +19 -0
  42. package/dist/jsxToLitHtml/config.d.ts +148 -0
  43. package/dist/jsxToLitHtml/convertProps.d.ts +10 -0
  44. package/dist/jsxToLitHtml/escapeForTemplateLiteral.d.ts +45 -0
  45. package/dist/jsxToLitHtml/imports.d.ts +32 -0
  46. package/dist/jsxToLitHtml/index.d.ts +17 -0
  47. package/dist/jsxToLitHtml/inferPropType.d.ts +40 -0
  48. package/dist/jsxToLitHtml/insertRepeatCall.d.ts +49 -0
  49. package/dist/jsxToLitHtml/jsxVisitor.d.ts +11 -0
  50. package/dist/jsxToLitHtml/templateParts.d.ts +17 -0
  51. package/dist/jsxToLitHtml/throwOnImportingExternalized.d.ts +10 -0
  52. package/dist/jsxToLitHtml/types.d.ts +80 -0
  53. package/dist/jsxToLitHtml/utils.d.ts +14 -0
  54. package/dist/jsxToLitHtml/utils.spec.d.ts +1 -0
  55. package/dist/manifests/complexTypes/addComponentMetadata.d.ts +5 -0
  56. package/dist/manifests/complexTypes/addMethodMetadata.d.ts +6 -0
  57. package/dist/manifests/complexTypes/addPropMetadata.d.ts +8 -0
  58. package/dist/manifests/complexTypes/docsUtils.d.ts +18 -0
  59. package/dist/manifests/complexTypes/event.d.ts +9 -0
  60. package/dist/manifests/complexTypes/getComplexPropertyType.d.ts +11 -0
  61. package/dist/manifests/complexTypes/transformUtils.d.ts +130 -0
  62. package/dist/manifests/complexTypes/transformUtils.spec.d.ts +1 -0
  63. package/dist/manifests/complexTypes/typeToEnum.d.ts +14 -0
  64. package/dist/manifests/complexTypes/typeToEnum.spec.d.ts +1 -0
  65. package/dist/manifests/complexTypes/types.d.ts +135 -0
  66. package/dist/manifests/config.d.ts +2 -0
  67. package/dist/manifests/createManifest.d.ts +39 -0
  68. package/dist/manifests/customElementDecoratorPlugins.d.ts +58 -0
  69. package/dist/manifests/customElementDecoratorPlugins.spec.d.ts +1 -0
  70. package/dist/manifests/hideUntilHydrated.d.ts +15 -0
  71. package/dist/manifests/index.d.ts +12 -0
  72. package/dist/manifests/kebabCaseAttributes.d.ts +18 -0
  73. package/dist/manifests/lazy.d.ts +22 -0
  74. package/dist/manifests/lazy.spec.d.ts +1 -0
  75. package/dist/manifests/stencilManifest.d.ts +17 -0
  76. package/dist/manifests/storybookManifest.d.ts +6 -0
  77. package/dist/manifests/types.d.ts +1 -0
  78. package/dist/manifests/utils.d.ts +17 -0
  79. package/dist/plugins/buildCdn.d.ts +14 -0
  80. package/dist/plugins/buildStencilHydrate.d.ts +16 -0
  81. package/dist/plugins/buildWrappers.d.ts +3 -0
  82. package/dist/plugins/configureVite.d.ts +19 -0
  83. package/dist/plugins/externalizeDependencies.d.ts +34 -0
  84. package/dist/plugins/externalizeDependencies.spec.d.ts +1 -0
  85. package/dist/plugins/generateDocs.d.ts +10 -0
  86. package/dist/plugins/handleDynamicAssets.d.ts +3 -0
  87. package/dist/plugins/handleStaticAssets.d.ts +9 -0
  88. package/dist/plugins/loadLitCss.d.ts +89 -0
  89. package/dist/plugins/printTotalBuildSize.d.ts +7 -0
  90. package/dist/plugins/provideAssets.d.ts +53 -0
  91. package/dist/plugins/provideAssets.spec.d.ts +1 -0
  92. package/dist/plugins/setAssetsPath.d.ts +10 -0
  93. package/dist/plugins/updatePackageJson.d.ts +9 -0
  94. package/dist/plugins/updatePackageJson.spec.d.ts +1 -0
  95. package/dist/publicTypes.d.ts +626 -0
  96. package/dist/puppeteer-testing/globalSetup.d.ts +72 -0
  97. package/dist/puppeteer-testing/globalSetup.js +11 -0
  98. package/dist/puppeteer-testing/index.d.ts +9 -0
  99. package/dist/puppeteer-testing/index.js +6 -0
  100. package/dist/puppeteer-testing/injected.d.ts +8 -0
  101. package/dist/puppeteer-testing/puppeteer/browser.d.ts +6 -0
  102. package/dist/puppeteer-testing/puppeteer/element.d.ts +219 -0
  103. package/dist/puppeteer-testing/puppeteer/events.d.ts +21 -0
  104. package/dist/puppeteer-testing/puppeteer/page.d.ts +5 -0
  105. package/dist/puppeteer-testing/puppeteer/types.d.ts +124 -0
  106. package/dist/puppeteer-testing/vitest/matchers/attributes.d.ts +4 -0
  107. package/dist/puppeteer-testing/vitest/matchers/classList.d.ts +4 -0
  108. package/dist/puppeteer-testing/vitest/matchers/events.d.ts +7 -0
  109. package/dist/puppeteer-testing/vitest/matchers/index.d.ts +38 -0
  110. package/dist/puppeteer-testing/vitest/matchers/text.d.ts +2 -0
  111. package/dist/puppeteer-testing/vitest/matchers/utils.d.ts +1 -0
  112. package/dist/puppeteer-testing/vitest/runner.d.ts +15 -0
  113. package/dist/puppeteer-testing/vitest/setupFile.d.ts +1 -0
  114. package/dist/testing/index.d.ts +11 -0
  115. package/dist/testing/index.js +1 -0
  116. package/dist/testing/mount.d.ts +106 -0
  117. package/dist/testing/setupFile.d.ts +1 -0
  118. package/dist/testing/snapshotSerializer.d.ts +12 -0
  119. package/dist/testing/wrapController.d.ts +33 -0
  120. package/dist/tests/utils.d.ts +4 -0
  121. package/dist/transformers/guardAgainstInternalJsDoc.d.ts +11 -0
  122. package/dist/transformers/index.d.ts +22 -0
  123. package/dist/transformers/injectRuntimeOptions.d.ts +3 -0
  124. package/dist/transformers/internalTypeScriptApis.d.ts +29 -0
  125. package/dist/transformers/liftDecorators.d.ts +21 -0
  126. package/dist/transformers/members.d.ts +12 -0
  127. package/dist/transformers/property.d.ts +9 -0
  128. package/dist/transformers/propertyOptions.d.ts +111 -0
  129. package/dist/transformers/updateOriginalFile.d.ts +20 -0
  130. package/dist/transformers/utils.d.ts +14 -0
  131. package/dist/types/astTransformers.d.ts +3 -0
  132. package/dist/types/hideInternalLitElement.d.ts +9 -0
  133. package/dist/types/index.d.ts +18 -0
  134. package/dist/types/liftSetterTypes.d.ts +33 -0
  135. package/dist/types/textTransformers.d.ts +4 -0
  136. package/dist/types/transformComponentMembers.d.ts +10 -0
  137. package/dist/useLumina.d.ts +13 -0
  138. package/dist/utils/error.d.ts +4 -0
  139. package/dist/utils/packageJson.d.ts +24 -0
  140. package/dist/utils/path.d.ts +25 -0
  141. package/dist/utils/path.spec.d.ts +1 -0
  142. 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,8 @@
1
+ import { type ProvidedContext } from "vitest";
2
+ /**
3
+ * Convenience wrapper around "inject()" API to improve DX
4
+ *
5
+ * With this "Go to definition" and "refactor -> rename" IDE features work
6
+ * better.
7
+ */
8
+ export declare const injected: ProvidedContext;
@@ -0,0 +1,6 @@
1
+ import type { Browser } from "puppeteer";
2
+ /**
3
+ * This is called when test is executing in a non-main thread. We connect to
4
+ * the browser instance using a web socket.
5
+ */
6
+ export declare function connectBrowser(): Promise<Browser>;
@@ -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,5 @@
1
+ import type { E2EPage } from "./types";
2
+ export type NewE2EPageOptions = {
3
+ html?: string;
4
+ };
5
+ export declare function newE2EPage(options: NewE2EPageOptions): Promise<E2EPage>;
@@ -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 } from "@vitest/expect";
2
+ export declare const toEqualAttribute: RawMatcherFn;
3
+ export declare const toEqualAttributes: RawMatcherFn;
4
+ export declare const toHaveAttribute: RawMatcherFn;
@@ -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,2 @@
1
+ import type { RawMatcherFn } from "@vitest/expect";
2
+ export declare const toEqualText: RawMatcherFn;
@@ -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};