@@ -2,7 +2,8 @@ const path = require('path');
22
33// we must use a relative path here instead of tsconfig#paths
44// see https://github.com/monounity/karma-typescript/issues/315
5- import * as d from '../../internal' ;
5+ // Deprecated: replaced by jest-dom-utils.ts
6+ export { } ;
67
78/**
89 * Utilities for creating a test bed to execute HTML rendering tests against
@@ -26,193 +27,4 @@ type DomTestUtilities = {
2627 * @param document a `Document` compliant entity where tests may be rendered
2728 * @returns utilities to set up the DOM and tear it down within the test bed
2829 */
29- export function setupDomTests ( document : Document ) : DomTestUtilities {
30- /**
31- * All HTML will be rendered as a child of the test bed - get it from the current document (and create it, if it
32- * doesn't exist) so that it is available for all future tests.
33- */
34- let testBed = document . getElementById ( 'test-app' ) ;
35- if ( ! testBed ) {
36- testBed = document . createElement ( 'div' ) ;
37- testBed . id = 'test-app' ;
38- document . body . appendChild ( testBed ) ;
39- }
40-
41- /**
42- * @see {@link DomTestUtilities#setupDom }
43- */
44- function setupDom ( url : string ) : Promise < HTMLElement > {
45- const testElement = document . createElement ( 'div' ) ;
46- testElement . className = 'test-spec' ;
47-
48- if ( ! testBed ) {
49- console . error ( 'The Stencil/Karma test bed could not be found.' ) ;
50- process . exit ( 1 ) ;
51- }
52-
53- testBed . appendChild ( testElement ) ;
54-
55- return renderTest ( url , testElement ) ;
56- }
57-
58- /**
59- * Render HTML for executing tests against.
60- * @param url the location on disk containing the HTML to load
61- * @param testElement a parent HTML element to place test code in
62- * @returns the fully rendered HTML to test against
63- */
64- function renderTest ( url : string , testElement : HTMLElement ) : Promise < HTMLElement > {
65- // 'base' is the directory that karma will serve all assets from
66- url = path . join ( 'base' , url ) ;
67-
68- return new Promise < HTMLElement > ( ( resolve , reject ) => {
69- /**
70- * Callback to be invoked following the retrieval of the file containing the HTML to load
71- * @param this the `XMLHttpRequest` instance that requested the HTML
72- */
73- const indexHtmlLoaded = function ( this : XMLHttpRequest ) : void {
74- if ( this . status !== 200 ) {
75- reject ( `404: ${ url } ` ) ;
76- return ;
77- }
78-
79- testElement . innerHTML = this . responseText ;
80-
81- /**
82- * Re-generate script tags that are embedded in the loaded HTML file.
83- *
84- * Doing so allows JS files to be loaded (via script tags), when the HTML is served, without having to configure
85- * Karma to load the JS explicitly. This is done by adding the host/port combination to existing `src`
86- * attributes.
87- *
88- * Before:
89- * ```html
90- * <script type="module" src="/index.6127a5ed.js"></script>
91- * ```
92- *
93- * After:
94- * ```html
95- * <script src="http://localhost:9876/index.547a265b.js" type="module"></script>
96- * ```
97- */
98- const parseAndRebuildScriptTags = ( ) => {
99- const tempScripts : NodeListOf < HTMLScriptElement > = testElement . querySelectorAll ( 'script' ) ;
100- for ( let i = 0 ; i < tempScripts . length ; i ++ ) {
101- const script : HTMLScriptElement = document . createElement ( 'script' ) ;
102- if ( tempScripts [ i ] . src ) {
103- script . src = tempScripts [ i ] . src ;
104- }
105- if ( tempScripts [ i ] . hasAttribute ( 'nomodule' ) ) {
106- script . setAttribute ( 'nomodule' , '' ) ;
107- }
108- if ( tempScripts [ i ] . hasAttribute ( 'type' ) ) {
109- const typeAttribute = tempScripts [ i ] . getAttribute ( 'type' ) ;
110- if ( typeof typeAttribute === 'string' ) {
111- // older DOM implementations would return an empty string to designate `null`
112- // here, we interpret the empty string to be a valid value
113- script . setAttribute ( 'type' , typeAttribute ) ;
114- }
115- }
116- script . innerHTML = tempScripts [ i ] . innerHTML ;
117-
118- if ( tempScripts [ i ] . parentNode ) {
119- // the scripts were found by querying a common parent node, which _should_ still exist
120- tempScripts [ i ] . parentNode ! . insertBefore ( script , tempScripts [ i ] ) ;
121- tempScripts [ i ] . parentNode ! . removeChild ( tempScripts [ i ] ) ;
122- } else {
123- // if for some reason the parent node no longer exists, something's manipulated it while we were parsing
124- // the script tags. this can lead to undesirable & hard to debug behavior, fail.
125- reject ( 'the parent node for script tags no longer exists. exiting.' ) ;
126- }
127- }
128- } ;
129-
130- parseAndRebuildScriptTags ( ) ;
131-
132- /**
133- * Create a listener for Stencil's "appload" event to signal to the test framework the application and its
134- * children have finished loading
135- */
136- const onAppLoad = ( ) => {
137- window . removeEventListener ( 'appload' , onAppLoad ) ;
138- allReady ( ) . then ( ( ) => {
139- resolve ( testElement ) ;
140- } ) ;
141- } ;
142- window . addEventListener ( 'appload' , onAppLoad ) ;
143- } ;
144-
145- /**
146- * Ensure that all `onComponentReady` functions on Stencil elements in the DOM have been called before rendering
147- * @returns an array of promises, one for each `onComponentReady` found on a Stencil component
148- */
149- const allReady = ( ) : Promise < d . HTMLStencilElement [ ] | void > => {
150- const promises : Promise < d . HTMLStencilElement > [ ] = [ ] ;
151-
152- /**
153- * Function that recursively traverses the DOM, looking for Stencil components. Any `componentOnReady`
154- * functions found on Stencil components are pushed to a buffer to be run after traversing the entire DOM.
155- * @param elm the current element being inspected
156- */
157- const waitForDidLoad = ( elm : Element ) : void => {
158- if ( elm != null && elm . nodeType === 1 ) {
159- // the element exists and is an `ELEMENT_NODE`
160- for ( let i = 0 ; i < elm . children . length ; i ++ ) {
161- const childElm = elm . children [ i ] ;
162- if ( childElm . tagName . includes ( '-' ) && isHtmlStencilElement ( childElm ) ) {
163- promises . push ( childElm . componentOnReady ( ) ) ;
164- }
165- waitForDidLoad ( childElm ) ;
166- }
167- }
168- } ;
169-
170- // recursively walk the DOM to find all `onComponentReady` functions
171- waitForDidLoad ( window . document . documentElement ) ;
172-
173- return Promise . all ( promises ) . catch ( ( e ) => console . error ( e ) ) ;
174- } ;
175-
176- try {
177- const testHtmlRequest = new XMLHttpRequest ( ) ;
178- testHtmlRequest . addEventListener ( 'load' , indexHtmlLoaded ) ;
179- testHtmlRequest . addEventListener ( 'error' , ( err ) => {
180- console . error ( 'error testHtmlRequest.addEventListener' , err ) ;
181- reject ( err ) ;
182- } ) ;
183- testHtmlRequest . open ( 'GET' , url ) ;
184- testHtmlRequest . send ( ) ;
185- } catch ( e : unknown ) {
186- console . error ( 'catch error' , e ) ;
187- reject ( e ) ;
188- }
189- } ) ;
190- }
191-
192- /**
193- * @see {@link DomTestUtilities#tearDownDom }
194- */
195- function tearDownDom ( ) : void {
196- if ( testBed ) {
197- testBed . innerHTML = '' ;
198- }
199- }
200-
201- return { setupDom, tearDownDom } ;
202- }
203-
204- /**
205- * Type guard to verify some entity is an instance of Stencil HTML Element
206- * @param elm the entity to test
207- * @returns `true` if the entity is a Stencil HTML Element, `false` otherwise
208- */
209- function isHtmlStencilElement ( elm : unknown ) : elm is d . HTMLStencilElement {
210- // `hasOwnProperty` does not act as a type guard/narrow `elm` in any way, so we use an assertion to verify that
211- // `onComponentReady` is a function
212- return (
213- elm != null &&
214- typeof elm === 'object' &&
215- elm . hasOwnProperty ( 'onComponentReady' ) &&
216- typeof ( elm as any ) . onComponentReady === 'function'
217- ) ;
218- }
30+ //
0 commit comments