1- import { spyConsole } from './wtr-utils.mjs' ;
2-
3- function pass ( ) {
4- return {
5- pass : true ,
6- } ;
7- }
8-
9- function fail ( message ) {
10- return {
11- pass : false ,
12- message : message ,
13- } ;
14- }
15-
16- function formatConsoleCall ( args ) {
17- return args . map ( String ) . join ( ' ' ) ;
18- }
19-
20- // TODO [#869]: Improve lookup logWarning doesn't use console.group anymore.
21- function consoleDevMatcherFactory ( methodName , expectInProd ) {
22- return function consoleDevMatcher ( ) {
23- return {
24- negativeCompare : function negativeCompare ( actual ) {
25- const spy = spyConsole ( ) ;
26- try {
27- actual ( ) ;
28- } finally {
29- spy . reset ( ) ;
30- }
31-
32- const callsArgs = spy . calls [ methodName ] ;
33- const formattedCalls = callsArgs
34- . map ( function ( arg ) {
35- return '"' + formatConsoleCall ( arg ) + '"' ;
36- } )
37- . join ( ', ' ) ;
38-
39- if ( callsArgs . length === 0 ) {
40- return {
41- pass : true ,
42- } ;
43- }
44- return {
45- pass : false ,
46- message : function ( ) {
47- return 'Expect no message but received:\n' + formattedCalls ;
48- } ,
49- } ;
50- } ,
51- compare : function compare ( actual , expectedMessages ) {
52- function matchMessage ( message , expectedMessage ) {
53- if ( typeof expectedMessage === 'string' ) {
54- return message === expectedMessage ;
55- } else {
56- return expectedMessage . test ( message ) ;
57- }
58- }
59-
60- if ( ! Array . isArray ( expectedMessages ) ) {
61- expectedMessages = [ expectedMessages ] ;
62- }
63-
64- if ( typeof actual !== 'function' ) {
65- throw new Error ( 'Expected function to throw error.' ) ;
66- } else if (
67- expectedMessages . some ( function ( message ) {
68- return typeof message !== 'string' && ! ( message instanceof RegExp ) ;
69- } )
70- ) {
71- throw new Error (
72- 'Expected a string or a RegExp to compare the thrown error against, or an array of such.'
73- ) ;
74- }
75-
76- const spy = spyConsole ( ) ;
77-
78- try {
79- actual ( ) ;
80- } finally {
81- spy . reset ( ) ;
82- }
83-
84- const callsArgs = spy . calls [ methodName ] ;
85- const formattedCalls = callsArgs
86- . map ( function ( callArgs ) {
87- return '"' + formatConsoleCall ( callArgs ) + '"' ;
88- } )
89- . join ( ', ' ) ;
90-
91- if ( ! expectInProd && process . env . NODE_ENV === 'production' ) {
92- if ( callsArgs . length !== 0 ) {
93- return fail (
94- 'Expected console.' +
95- methodName +
96- ' to never called in production mode, but it was called ' +
97- callsArgs . length +
98- ' with ' +
99- formattedCalls +
100- '.'
101- ) ;
102- } else {
103- return pass ( ) ;
104- }
105- } else {
106- if ( callsArgs . length === 0 ) {
107- return fail (
108- 'Expected console.' +
109- methodName +
110- ' to called with ' +
111- JSON . stringify ( expectedMessages ) +
112- ', but was never called.'
113- ) ;
114- } else {
115- if ( callsArgs . length !== expectedMessages . length ) {
116- return fail (
117- 'Expected console.' +
118- methodName +
119- ' to be called ' +
120- expectedMessages . length +
121- ' time(s), but was called ' +
122- callsArgs . length +
123- ' time(s).'
124- ) ;
125- }
126- for ( let i = 0 ; i < callsArgs . length ; i ++ ) {
127- const callsArg = callsArgs [ i ] ;
128- const expectedMessage = expectedMessages [ i ] ;
129- const actualMessage = formatConsoleCall ( callsArg ) ;
130- if ( ! matchMessage ( actualMessage , expectedMessage ) ) {
131- return fail (
132- 'Expected console.' +
133- methodName +
134- ' to be called with "' +
135- expectedMessage +
136- '", but was called with "' +
137- actualMessage +
138- '".'
139- ) ;
140- }
141- }
142- return pass ( ) ;
143- }
144- }
145- } ,
146- } ;
147- } ;
148- }
149-
150- function errorMatcherFactory ( errorListener , expectInProd ) {
151- return function toThrowError ( ) {
152- return {
153- compare : function ( actual , expectedErrorCtor , expectedMessage ) {
154- function matchMessage ( message ) {
155- if ( typeof expectedMessage === 'undefined' ) {
156- return true ;
157- } else if ( typeof expectedMessage === 'string' ) {
158- return message === expectedMessage ;
159- } else {
160- return expectedMessage . test ( message ) ;
161- }
162- }
163-
164- function matchError ( error ) {
165- return error instanceof expectedErrorCtor && matchMessage ( error . message ) ;
166- }
167-
168- function throwDescription ( thrown ) {
169- return thrown . name + ' with message "' + thrown . message + '"' ;
170- }
171-
172- if ( typeof expectedMessage === 'undefined' ) {
173- if ( typeof expectedErrorCtor === 'undefined' ) {
174- // 0 arguments provided
175- expectedMessage = undefined ;
176- expectedErrorCtor = Error ;
177- } else {
178- // 1 argument provided
179- expectedMessage = expectedErrorCtor ;
180- expectedErrorCtor = Error ;
181- }
182- }
183-
184- if ( typeof actual !== 'function' ) {
185- throw new Error ( 'Expected function to throw error.' ) ;
186- } else if (
187- expectedErrorCtor !== Error &&
188- ! ( expectedErrorCtor . prototype instanceof Error )
189- ) {
190- throw new Error ( 'Expected an error constructor.' ) ;
191- } else if (
192- typeof expectedMessage !== 'undefined' &&
193- typeof expectedMessage !== 'string' &&
194- ! ( expectedMessage instanceof RegExp )
195- ) {
196- throw new Error (
197- 'Expected a string or a RegExp to compare the thrown error against.'
198- ) ;
199- }
200-
201- const thrown = errorListener ( actual ) ;
202-
203- if ( ! expectInProd && process . env . NODE_ENV === 'production' ) {
204- if ( thrown !== undefined ) {
205- return fail (
206- 'Expected function not to throw an error in production mode, but it threw ' +
207- throwDescription ( thrown ) +
208- '.'
209- ) ;
210- } else {
211- return pass ( ) ;
212- }
213- } else {
214- if ( thrown === undefined ) {
215- return fail (
216- 'Expected function to throw an ' +
217- expectedErrorCtor . name +
218- ' error in development mode"' +
219- ( expectedMessage ? 'with message ' + expectedMessage : '' ) +
220- '".'
221- ) ;
222- } else if ( ! matchError ( thrown ) ) {
223- return fail (
224- 'Expected function to throw an ' +
225- expectedErrorCtor . name +
226- ' error in development mode "' +
227- ( expectedMessage ? 'with message ' + expectedMessage : '' ) +
228- '", but it threw ' +
229- throwDescription ( thrown ) +
230- '.'
231- ) ;
232- } else {
233- return pass ( ) ;
234- }
235- }
236- } ,
237- } ;
238- } ;
239- }
240-
241- // Listen for errors thrown directly by the callback
242- function directErrorListener ( callback ) {
243- try {
244- callback ( ) ;
245- } catch ( error ) {
246- return error ;
247- }
248- }
249-
250- // Listen for errors using window.addEventListener('error')
251- function windowErrorListener ( callback ) {
252- let error ;
253- function onError ( event ) {
254- event . preventDefault ( ) ; // don't log the error
255- error = event . error ;
256- }
257-
258- // Prevent jasmine from handling the global error. There doesn't seem to be another
259- // way to disable this behavior: https://github.com/jasmine/jasmine/pull/1860
260- const originalOnError = window . onerror ;
261- window . onerror = null ;
262- window . addEventListener ( 'error' , onError ) ;
263-
264- try {
265- callback ( ) ;
266- } finally {
267- window . onerror = originalOnError ;
268- window . removeEventListener ( 'error' , onError ) ;
269- }
270- return error ;
271- }
272-
273- // For errors we expect to be thrown in the connectedCallback() phase
274- // of a custom element, there are two possibilities:
275- // 1) We're using non-native lifecycle callbacks, so the error is thrown synchronously
276- // 2) We're using native lifecycle callbacks, so the error is thrown asynchronously and can
277- // only be caught with window.addEventListener('error')
278- // - Note native lifecycle callbacks are all thrown asynchronously.
279- function customElementCallbackReactionErrorListener ( callback ) {
280- return lwcRuntimeFlags . DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE
281- ? directErrorListener ( callback )
282- : windowErrorListener ( callback ) ;
283- }
284-
285- // export const toLogErrorDev = consoleDevMatcherFactory('error');
286- // export const toLogError = consoleDevMatcherFactory('error', true);
287- // export const toLogWarningDev = consoleDevMatcherFactory('warn');
288- // export const toThrowErrorDev = errorMatcherFactory(directErrorListener);
289- // export const toThrowCallbackReactionErrorDev = errorMatcherFactory(
290- // customElementCallbackReactionErrorListener
291- // );
292- // export const toThrowCallbackReactionError = errorMatcherFactory(
293- // customElementCallbackReactionErrorListener,
294- // true
295- // );
296- // export const toThrowCallbackReactionErrorEvenInSyntheticLifecycleMode = errorMatcherFactory(
297- // windowErrorListener,
298- // true
299- // );
1+ // FIXME: copy implementations from karma tests
3002
3013const customMatchers = [
3024 // LWC custom
@@ -315,7 +17,7 @@ const customMatchers = [
31517export const registerCustomMatchers = ( chai , utils ) => {
31618 for ( const matcher of customMatchers ) {
31719 utils . addMethod ( chai . Assertion . prototype , matcher , function ( ) {
318- // TODO : implement for realsies
20+ // FIXME : implement for realsies
31921 const fn = utils . flag ( this , 'object' ) ;
32022 if ( typeof fn === 'function' ) {
32123 try {
0 commit comments