How to use removeMeAndAbove method in Cypress

Best JavaScript code snippet using cypress

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

error_utils_spec.js

Source: error_utils_spec.js Github

copy
1const $errUtils = require('@packages/driver/src/cypress/error_utils')
2const $stackUtils = require('@packages/driver/src/cypress/stack_utils')
3const $errorMessages = require('@packages/driver/src/cypress/error_messages')
4
5describe('driver/src/cypress/error_utils', () => {
6  context('.modifyErrMsg', () => {
7    let originalErr
8    let newErrMsg
9    let modifier
10
11    beforeEach(() => {
12      originalErr = new Error('simple foo message')
13      originalErr.name = 'FooError'
14      newErrMsg = 'new message'
15      modifier = (msg1, msg2) => `${msg2} ${msg1}`
16    })
17
18    it('returns new error object with message modified by callback', () => {
19      const err = $errUtils.modifyErrMsg(originalErr, newErrMsg, modifier)
20
21      expect(err.name).to.eq('FooError')
22      expect(err.message).to.eq('new message simple foo message')
23    })
24
25    it('replaces stack error message', () => {
26      originalErr.stack = `${originalErr.name}: ${originalErr.message}\nline 2\nline 3`
27      const err = $errUtils.modifyErrMsg(originalErr, newErrMsg, modifier)
28
29      expect(err.stack).to.equal('FooError: new message simple foo message\nline 2\nline 3')
30    })
31
32    it('keeps other properties in place from original error', () => {
33      originalErr.actual = 'foo'
34      originalErr.expected = 'bar'
35      const err = $errUtils.modifyErrMsg(originalErr, newErrMsg, modifier)
36
37      expect(err.actual).to.equal('foo')
38      expect(err.expected).to.equal('bar')
39    })
40  })
41
42  context('.throwErr', () => {
43    it('throws error as a cypress error when it is a message string', () => {
44      const fn = () => {
45        $errUtils.throwErr('Something unexpected')
46      }
47
48      expect(fn).to.throw().and.satisfy((err) => {
49        expect(err.message).to.equal('Something unexpected')
50        expect(err.name).to.eq('CypressError')
51
52        return true
53      })
54    })
55
56    it('throws error when it is an object', () => {
57      const fn = () => {
58        $errUtils.throwErr({ name: 'SomeError', message: 'Something unexpected', extraProp: 'extra prop' })
59      }
60
61      expect(fn).to.throw().and.satisfy((err) => {
62        expect(err.message).to.equal('Something unexpected')
63        expect(err.name).to.eq('SomeError')
64        expect(err.extraProp).to.eq('extra prop')
65
66        return true
67      })
68    })
69
70    it('throws error when it is an error', () => {
71      const err = new Error('Something unexpected')
72
73      err.extraProp = 'extra prop'
74      const fn = () => {
75        $errUtils.throwErr(err)
76      }
77
78      expect(fn).to.throw().and.satisfy((err) => {
79        expect(err.message).to.equal('Something unexpected')
80        expect(err.name).to.eq('Error')
81        expect(err.extraProp).to.eq('extra prop')
82
83        return true
84      })
85    })
86
87    it('attaches onFail to the error when it is a function', () => {
88      const onFail = function () {}
89      const fn = () => $errUtils.throwErr(new Error('foo'), { onFail })
90
91      expect(fn).throw().and.satisfy((err) => {
92        expect(err.onFail).to.equal(onFail)
93
94        return true
95      })
96    })
97
98    it('attaches onFail to the error when it is a command', () => {
99      const command = { error: cy.spy() }
100      const fn = () => $errUtils.throwErr(new Error('foo'), { onFail: command })
101
102      expect(fn).throw().and.satisfy((err) => {
103        err.onFail('the error')
104
105        expect(command.error).to.be.calledWith('the error')
106
107        return true
108      })
109    })
110  })
111
112  context('.errByPath', () => {
113    beforeEach(() => {
114      $errorMessages.__test_errors = {
115        obj: {
116          message: 'This is a simple error message',
117          docsUrl: 'https://on.link.io',
118        },
119        obj_with_args: {
120          message: `This has args like '{{foo}}' and {{bar}}`,
121          docsUrl: 'https://on.link.io',
122        },
123        obj_with_multi_args: {
124          message: `This has args like '{{foo}}' and {{bar}}, and '{{foo}}' is used twice`,
125          docsUrl: 'https://on.link.io',
126        },
127        obj_with_markdown: {
128          message: 'This has markdown like `{{foo}}`, *{{bar}}*, **{{foo}}**, and _{{bar}}_',
129          docsUrl: 'https://on.link.io',
130        },
131        str: 'This is a simple error message',
132        str_with_args: `This has args like '{{foo}}' and {{bar}}`,
133        str_with_multi_args: `This has args like '{{foo}}' and {{bar}}, and '{{foo}}' is used twice`,
134        str_with_markdown: 'This has markdown like `{{foo}}`, *{{bar}}*, **{{foo}}**, and _{{bar}}_',
135        fn () {
136          return 'This is a simple error message'
137        },
138        fn_with_args (obj) {
139          return `This has args like '${obj.foo}' and ${obj.bar}`
140        },
141        fn_with_multi_args (obj) {
142          return `This has args like '${obj.foo}' and ${obj.bar}, and '${obj.foo}' is used twice`
143        },
144        fn_with_markdown (obj) {
145          return `This has markdown like \`${obj.foo}\`, *${obj.bar}*, **${obj.foo}**, and _${obj.bar}_`
146        },
147        fn_returns_obj: () => {
148          return {
149            message: 'This is a simple error message',
150            docsUrl: 'https://on.link.io',
151          }
152        },
153        fn_returns_obj_with_args: (obj) => {
154          return {
155            message: `This has args like '${obj.foo}' and ${obj.bar}`,
156            docsUrl: 'https://on.link.io',
157          }
158        },
159        fn_returns_obj_with_multi_args: (obj) => {
160          return {
161            message: `This has args like '${obj.foo}' and ${obj.bar}, and '${obj.foo}' is used twice`,
162            docsUrl: 'https://on.link.io',
163          }
164        },
165        fn_returns_obj_with_markdown: (obj) => {
166          return {
167            message: `This has markdown like \`${obj.foo}\`, *${obj.bar}*, **${obj.foo}**, and _${obj.bar}_`,
168            docsUrl: 'https://on.link.io',
169          }
170        },
171      }
172    })
173
174    it('returns internal error when message path does not exist', () => {
175      const err = $errUtils.errByPath('not.there')
176
177      expect(err.name).to.eq('InternalCypressError')
178      expect(err.message).to.include(`Error message path 'not.there' does not exist`)
179    })
180
181    describe('when message value is an object', () => {
182      it('has correct name, message, and docs url when path exists', () => {
183        const err = $errUtils.errByPath('__test_errors.obj')
184
185        expect(err.name).to.eq('CypressError')
186        expect(err.message).to.include('This is a simple error message')
187        expect(err.docsUrl).to.include('https://on.link.io')
188      })
189
190      it('uses args provided for the error', () => {
191        const err = $errUtils.errByPath('__test_errors.obj_with_args', {
192          foo: 'foo', bar: ['bar', 'qux'],
193        })
194
195        expect(err.message).to.include('This has args like \'foo\' and bar,qux')
196        expect(err.docsUrl).to.include('https://on.link.io')
197      })
198
199      it('handles args being used multiple times in message', () => {
200        const err = $errUtils.errByPath('__test_errors.obj_with_multi_args', {
201          foo: 'foo', bar: ['bar', 'qux'],
202        })
203
204        expect(err.message).to.include('This has args like \'foo\' and bar,qux, and \'foo\' is used twice')
205        expect(err.docsUrl).to.include('https://on.link.io')
206      })
207
208      it('formats markdown in the error message', () => {
209        const err = $errUtils.errByPath('__test_errors.obj_with_markdown', {
210          foo: 'foo', bar: ['bar', 'qux'],
211        })
212
213        expect(err.message).to.include('This has markdown like `foo`, *bar,qux*, **foo**, and _bar,qux_')
214        expect(err.docsUrl).to.include('https://on.link.io')
215      })
216    })
217
218    describe('when message value is a string', () => {
219      it('has correct name, message, and docs url', () => {
220        const err = $errUtils.errByPath('__test_errors.str')
221
222        expect(err.name).to.eq('CypressError')
223        expect(err.message).to.include('This is a simple error message')
224        expect(err.docsUrl).to.be.undefined
225      })
226
227      it('uses args provided for the error', () => {
228        const err = $errUtils.errByPath('__test_errors.str_with_args', {
229          foo: 'foo', bar: ['bar', 'qux'],
230        })
231
232        expect(err.message).to.include('This has args like \'foo\' and bar,qux')
233      })
234
235      it('handles args being used multiple times in message', () => {
236        const err = $errUtils.errByPath('__test_errors.str_with_multi_args', {
237          foo: 'foo', bar: ['bar', 'qux'],
238        })
239
240        expect(err.message).to.include(`This has args like 'foo' and bar,qux, and 'foo' is used twice`)
241      })
242
243      it('formats markdown in the error message', () => {
244        const err = $errUtils.errByPath('__test_errors.str_with_markdown', {
245          foo: 'foo', bar: ['bar', 'qux'],
246        })
247
248        expect(err.message).to.include('This has markdown like `foo`, *bar,qux*, **foo**, and _bar,qux_')
249      })
250    })
251
252    describe('when message value is a function that returns a string', () => {
253      it('has correct name and message', () => {
254        const err = $errUtils.errByPath('__test_errors.fn')
255
256        expect(err.name).to.eq('CypressError')
257        expect(err.message).to.include('This is a simple error message')
258
259        return true
260      })
261
262      it('uses args in the error message', () => {
263        const err = $errUtils.errByPath('__test_errors.fn_with_args', {
264          foo: 'foo', bar: ['bar', 'qux'],
265        })
266
267        expect(err.message).to.include('This has args like \'foo\' and bar,qux')
268      })
269
270      it('handles args being used multiple times in message', () => {
271        const err = $errUtils.errByPath('__test_errors.fn_with_multi_args', {
272          foo: 'foo', bar: ['bar', 'qux'],
273        })
274
275        expect(err.message).to.include('This has args like \'foo\' and bar,qux, and \'foo\' is used twice')
276      })
277
278      it('formats markdown in the error message', () => {
279        const err = $errUtils.errByPath('__test_errors.fn_with_markdown', {
280          foo: 'foo', bar: ['bar', 'qux'],
281        })
282
283        expect(err.message).to.include('This has markdown like `foo`, *bar,qux*, **foo**, and _bar,qux_')
284      })
285    })
286
287    describe('when message value is a function that returns an object', () => {
288      describe('when no args are provided for the error', () => {
289        it('has an err.name of CypressError', () => {
290          const err = $errUtils.errByPath('__test_errors.fn_returns_obj')
291
292          expect(err.name).to.eq('CypressError')
293        })
294
295        it('has the right message and docs url', () => {
296          const err = $errUtils.errByPath('__test_errors.fn_returns_obj')
297
298          expect(err.message).to.include('This is a simple error message')
299          expect(err.docsUrl).to.include('https://on.link.io')
300        })
301      })
302
303      describe('when args are provided for the error', () => {
304        it('uses them in the error message', () => {
305          const err = $errUtils.errByPath('__test_errors.fn_returns_obj_with_args', {
306            foo: 'foo', bar: ['bar', 'qux'],
307          })
308
309          expect(err.message).to.include('This has args like \'foo\' and bar,qux')
310          expect(err.docsUrl).to.include('https://on.link.io')
311        })
312      })
313
314      describe('when args are provided for the error and some are used multiple times in message', () => {
315        it('uses them in the error message', () => {
316          const err = $errUtils.errByPath('__test_errors.fn_returns_obj_with_multi_args', {
317            foo: 'foo', bar: ['bar', 'qux'],
318          })
319
320          expect(err.message).to.include('This has args like \'foo\' and bar,qux, and \'foo\' is used twice')
321          expect(err.docsUrl).to.include('https://on.link.io')
322        })
323      })
324    })
325  })
326
327  context('.throwErrByPath', () => {
328    let fn
329
330    beforeEach(() => {
331      $errorMessages.__test_errors = {
332        test: 'Simple error {{message}}',
333      }
334
335      // build up a little stack
336      const throwingFn = () => {
337        $errUtils.throwErrByPath('__test_errors.test', {
338          args: { message: 'with a message' },
339        })
340      }
341
342      fn = () => throwingFn()
343    })
344
345    it('looks up error and throws it', () => {
346      expect(fn).to.throw('Simple error with a message')
347    })
348
349    it('removes internal stack lines from stack', () => {
350      // this features relies on Error.captureStackTrace, which some
351      // browsers don't have (e.g. Firefox)
352      if (!Error.captureStackTrace) return
353
354      expect(fn).to.throw().and.satisfies((err) => {
355        expect(err.stack).to.include('throwingFn')
356        expect(err.stack).not.to.include('throwErrByPath')
357        expect(err.stack).not.to.include('errByPath')
358        expect(err.stack).not.to.include('cypressErr')
359
360        return true
361      })
362    })
363  })
364
365  context('.throwErrByPath', () => {
366    it('looks up error and throws it', () => {
367      $errorMessages.__test_error = 'simple error message'
368
369      const fn = () => $errUtils.throwErrByPath('__test_error')
370
371      expect(fn).to.throw('simple error message')
372    })
373  })
374
375  context('.enhanceStack', () => {
376    const userInvocationStack = '  at userInvoked (app.js:1:1)'
377    const sourceStack = {
378      sourceMapped: 'source mapped stack',
379      parsed: [],
380    }
381    const codeFrame = {}
382    let err
383
384    beforeEach(() => {
385      cy.stub($stackUtils, 'replacedStack').returns('replaced stack')
386      cy.stub($stackUtils, 'stackWithUserInvocationStackSpliced').returns({ stack: 'spliced stack' })
387      cy.stub($stackUtils, 'getSourceStack').returns(sourceStack)
388      cy.stub($stackUtils, 'getCodeFrame').returns(codeFrame)
389
390      err = { stack: 'Error: original stack message\n at originalStack (foo.js:1:1)' }
391    })
392
393    it('replaces stack with user invocation stack', () => {
394      const result = $errUtils.enhanceStack({ err, userInvocationStack })
395
396      expect(result.stack).to.equal('replaced stack')
397    })
398
399    it('attaches source mapped stack', () => {
400      const result = $errUtils.enhanceStack({ err, userInvocationStack })
401
402      expect(result.sourceMappedStack).to.equal(sourceStack.sourceMapped)
403    })
404
405    it('attaches parsed stack', () => {
406      const result = $errUtils.enhanceStack({ err, userInvocationStack })
407
408      expect(result.parsedStack).to.equal(sourceStack.parsed)
409    })
410
411    it('attaches code frame', () => {
412      const result = $errUtils.enhanceStack({ err, userInvocationStack })
413
414      expect(result.codeFrame).to.equal(codeFrame)
415    })
416
417    it('appends user invocation stack when it is a cypress error', () => {
418      err.name = 'CypressError'
419
420      const result = $errUtils.enhanceStack({ err, userInvocationStack })
421
422      expect(result.stack).to.equal('spliced stack')
423    })
424
425    it('appends user invocation stack when it is a chai validation error', () => {
426      err.message = 'Invalid Chai property'
427
428      const result = $errUtils.enhanceStack({ err, userInvocationStack })
429
430      expect(result.stack).to.equal('spliced stack')
431    })
432
433    it('does not replaced or append stack when there is no invocation stack', () => {
434      const result = $errUtils.enhanceStack({ err })
435
436      expect(result.stack).to.equal(err.stack)
437    })
438  })
439
440  context('.appendErrMsg', () => {
441    it('replaces old stack message with new one', () => {
442      const err = new Error('old message')
443      const newErr = $errUtils.appendErrMsg(err, 'new message')
444
445      expect(newErr.message).to.equal('old message\n\nnew message')
446      expect(newErr.stack).to.include('Error: old message\n\nnew message\n')
447    })
448
449    it('properly replaces stack message when error has no message', () => {
450      const err = new Error()
451      const newErr = $errUtils.appendErrMsg(err, 'new message')
452
453      expect(newErr.message).to.equal('new message')
454      expect(newErr.stack).to.include('Error: new message\n')
455      expect(newErr.stack).not.to.include('\nError')
456    })
457  })
458
459  context('.createUncaughtException', () => {
460    let err
461    let state
462
463    beforeEach(() => {
464      err = new Error('original message')
465      err.stack = 'Error: original message\n\nat foo (path/to/file:1:1)'
466
467      state = cy.stub()
468    })
469
470    it('mutates the error passed in and returns it', () => {
471      const result = $errUtils.createUncaughtException({
472        frameType: 'spec',
473        handlerType: 'error',
474        state,
475        err,
476      })
477
478      expect(result).to.equal(err)
479    })
480
481    it('replaces message with wrapper message for spec error', () => {
482      const result = $errUtils.createUncaughtException({
483        frameType: 'spec',
484        handlerType: 'error',
485        state,
486        err,
487      })
488
489      expect(result.message).to.include('The following error originated from your test code, not from Cypress')
490      expect(result.message).to.include('> original message')
491    })
492
493    it('replaces message with wrapper message for app error', () => {
494      const result = $errUtils.createUncaughtException({
495        frameType: 'app',
496        handlerType: 'error',
497        state,
498        err,
499      })
500
501      expect(result.message).to.include('The following error originated from your application code, not from Cypress')
502      expect(result.message).to.include('> original message')
503    })
504
505    it('replaces original name and message in stack', () => {
506      const result = $errUtils.createUncaughtException({
507        frameType: 'spec',
508        handlerType: 'error',
509        state,
510        err,
511      })
512
513      expect(result.stack).not.to.include('Error: original message')
514    })
515
516    it('retains the stack of the original error', () => {
517      const result = $errUtils.createUncaughtException({
518        frameType: 'spec',
519        handlerType: 'error',
520        state,
521        err,
522      })
523
524      expect(result.stack).to.include('at foo (path/to/file:1:1)')
525    })
526
527    it('adds docsUrl for app error and original error', () => {
528      err.docsUrl = 'https://on.cypress.io/orginal-error-docs-url'
529
530      const result = $errUtils.createUncaughtException({
531        frameType: 'app',
532        handlerType: 'error',
533        state,
534        err,
535      })
536
537      expect(result.docsUrl).to.eql([
538        'https://on.cypress.io/uncaught-exception-from-application',
539        'https://on.cypress.io/orginal-error-docs-url',
540      ])
541    })
542
543    it('logs error with onFail fn when logs exists', () => {
544      const errorStub = cy.stub()
545
546      state.returns({
547        getLastLog: () => ({ error: errorStub }),
548      })
549
550      const result = $errUtils.createUncaughtException({
551        frameType: 'spec',
552        handlerType: 'error',
553        state,
554        err,
555      })
556
557      result.onFail()
558      expect(errorStub).to.be.calledWith(result)
559    })
560
561    it('does not error if no last log', () => {
562      state.returns({
563        getLastLog: () => {},
564      })
565
566      const result = $errUtils.createUncaughtException({
567        frameType: 'spec',
568        handlerType: 'error',
569        state,
570        err,
571      })
572
573      result.onFail()
574      // expect no error
575    })
576
577    it('does not error if no current command', () => {
578      state.returns(undefined)
579
580      const result = $errUtils.createUncaughtException({
581        frameType: 'spec',
582        handlerType: 'error',
583        state,
584        err,
585      })
586
587      result.onFail()
588      // expect no error
589    })
590  })
591
592  context('Error.captureStackTrace', () => {
593    it('works - even where not natively support', () => {
594      function removeMe2 () {
595        const err = {}
596
597        Error.captureStackTrace(err, removeMeAndAbove)
598
599        return err
600      }
601      function removeMe1 () {
602        return removeMe2()
603      }
604      function removeMeAndAbove () {
605        return removeMe1()
606      }
607      function dontRemoveMe () {
608        return removeMeAndAbove()
609      }
610
611      const stack = dontRemoveMe().stack
612
613      expect(stack).to.include('dontRemoveMe')
614      expect(stack).not.to.include('removeMe1')
615      expect(stack).not.to.include('removeMe2')
616      expect(stack).not.to.include('removeMeAndAbove')
617    })
618  })
619})
620
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Cypress on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)