How do I add additional data to Cypress failures? - javascript

I would like to log additional data when a test case fails. Where can I best insert my custom error handler?
For example:
cy.get('something')
.should('have.property', 'blah')
When this fails in the Cypress dashboard, I get:
CypressError: Timed out retrying: expected 'something' to have a property 'blah'
at Object.cypressErr (https://my.website.com/__cypress/runner/cypress_runner.js:65727:11)
at Object.throwErr (https://my.website.com/__cypress/runner/cypress_runner.js:65692:18)
at Object.throwErrByPath (https://my.website.com/__cypress/runner/cypress_runner.js:65719:17)
at retry (https://my.website.com/__cypress/runner/cypress_runner.js:59237:16)
at https://my.website.com/__cypress/runner/cypress_runner.js:51312:18
at tryCatcher (https://my.website.com/__cypress/runner/cypress_runner.js:131273:23)
at Promise._settlePromiseFromHandler (https://my.website.com/__cypress/runner/cypress_runner.js:129291:31)
at Promise._settlePromise (https://my.website.com/__cypress/runner/cypress_runner.js:129348:18)
at Promise._settlePromise0 (https://my.website.com/__cypress/runner/cypress_runner.js:129393:10)
at Promise._settlePromises (https://my.website.com/__cypress/runner/cypress_runner.js:129468:18)
at Async._drainQueue (https://my.website.com/__cypress/runner/cypress_runner.js:126197:16)
at Async._drainQueues (https://my.website.com/__cypress/runner/cypress_runner.js:126207:10)
at Async.drainQueues (https://my.website.com/__cypress/runner/cypress_runner.js:126081:14)
at <anonymous>
What I can do to customize this error, to something like:
CypressError: ...
My additional logging: {foo: 'bar', etc, etc}
Ultimately, I want to log some additional contextual data, so I can investigate + debug why a test may be failing/flaking.

I hope this library helps your need - https://github.com/cypress-io/error-message
Here is a gist out of it,
//Load the function from the module
const {formErrorText} = require('#cypress/error-message')
//Handle the error with custome messages
const fileSaveError = {
description: 'We could not save an important file',
solution: `Please check folder permissions and try again
more details on our FAQ page: https://faq.company.name
`
}
fs.writeFile(name)
.catch(
formErrorText(info).then(console.error)
)
/*
shows nice error message
------
We could not save an important file
Please check folder permissions and try again
more details on our FAQ page: https://faq.company.name
Exception message
------
Platform: darwin
Version: 15.6.2
*/
For more information, you can check this blog - https://www.cypress.io/blog/2017/07/26/good-error-messages/#Useful-E2E-assertion-failures
Edit 1:
As stated in comment, if you are looking for handling the mysterious failures, would suggest you to take a look at Cypress event handling mechanism. Here is the excerpt of it,
// likely want to do this in a support file
// so it's applied to all spec files
// cypress/support/index.js
Cypress.on('uncaught:exception', (err, runnable) => {
// Handle your logging logic here
})

Related

Vue3 + Vite: error handling in production

I used error handler from vue documentation
https://vuejs.org/guide/best-practices/production-deployment.html#tracking-runtime-errors
app.config.errorHandler = (err, instance, info) => {
console.log(err);
}
This works great with dev server, because it shows in which component the error happened and on what line it happened.
ReferenceError: foo is not defined
at ComponentNameWhereErrorHappened.vue:144:15
at callWithErrorHandling (runtime-core.esm-bundler.js:6737:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:6746:21)
at Array.job (runtime-core.esm-bundler.js:7154:17)
at flushPreFlushCbs (runtime-core.esm-bundler.js:6910:31)
at flushJobs (runtime-core.esm-bundler.js:6951:5)
But when I use this code in production, the code gets bundled (using Vite) and then the error handling is not useful anymore. Because the name of files changes and everything happens on line 1.
ReferenceError: foo is not defined
at ComponentNameButNotWhereErrorHappened.b61810f1.js:1:10588
at Pt (vendor.7753fa93.js:5:656)
at lt (vendor.7753fa93.js:5:735)
at Array._ (vendor.7753fa93.js:5:3255)
at Cl (vendor.7753fa93.js:5:1980)
at pf (vendor.7753fa93.js:5:2249)
Is there a way how to get useful information about runtime errors with production Vue code?
I solved it by adding sourcemap: true to the vite.config.js
export default defineConfig({
build: {
sourcemap: true
}
})

Electron Forge Error - cannot read property 'close' of undefined

I just set up a basic electron-react app by using electron-forge and adding React+webpack+typescript per instructions and it all works great (I haven't added anything beyond the basic setup). It compiles well with all green checkboxes.
However, when I hit the close button by mouse clicking the x in the top right, it shuts down but gives the following error:
An unhandled exception has occurred inside Forge:
Cannot read property 'close' of undefined
TypeError: Cannot read property 'close' of undefined
at WebpackPlugin.exitHandler (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\plugin-webpack\src\WebpackPlugin.ts:83:16)
at ChildProcess.<anonymous> (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\plugin-webpack\src\WebpackPlugin.ts:171:18)
at ChildProcess.emit (events.js:412:35)
at Process.ChildProcess._handle.onexit (internal/child_process.js:277:12)
C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\plugin-webpack\dist\WebpackPlugin.js:87
server.close();
^
TypeError: Cannot read property 'close' of undefined
at WebpackPlugin.exitHandler (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\plugin-webpack\src\WebpackPlugin.ts:83:16)
at process.<anonymous> (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\plugin-webpack\src\WebpackPlugin.ts:126:40)
at process.emit (events.js:412:35)
at process.emit (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\source-map-support\source-map-support.js:516:21)
at processEmit [as emit] (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\signal-exit\index.js:155:35)
at process.exit (internal/process/per_thread.js:169:15)
at process.<anonymous> (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\#electron-forge\cli\src\util\terminate.ts:20:11)
at process.emit (events.js:400:28)
at process.emit (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\source-map-support\source-map-support.js:516:21)
at processEmit [as emit] (C:\Users\cwebb\Documents\Webdev\Atlas\node_modules\signal-exit\index.js:161:32)
at process._fatalException (internal/process/execution.js:167:25)
Any recommendations as to how to correct this? I found one answer on a gitmemory site but it just said "thanks it worked" but no comment about how to fix the problem.
Thank you in advance for your help.
I just ran into this today and managed to find a hint here
You have to bind to the Electron app's window-all-closed event if you don't want this to happen. Usually, you'd use this event to quit the app when all the windows are closed. Here's an example snippet from main.js:
const { app } = require('electron')
app.on('window-all-closed', () => {
app.quit()
})
If you want the app to keep running after you close all windows, you can remove the call to app.quit, but make sure to keep the binding to window-all-closed. Having the binding prevents the exception from being thrown.

error creating stripe customer on create iOS and firebase

I am trying to create a stripe customer when the user creates an account on my IOS app. When I run the command firebase deploy --only functions All of my functions crash. but when I delete
const logging = require('#google-cloud/logging');
const stripe = require('stripe')(functions.config().stripe.token);
const currency = functions.config().stripe.currency || 'USD';
exports.createStripeCustomer = functions.auth.user().onCreate((user) => {
return stripe.customers.create({
email: user.email,
}).then((customer) => {
return admin.database().ref(`/stripe_customers/${user.uid}/customer_id`).set(customer.id);
});
});
I am receiving the error
Function failed on loading user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs
After going through my code I have narrowed it done to these lines. When I delete the three const, I receive the same error. If I delete the export and keep const, the same thing. My functions only push when I delete all of this. Is there something I am missing? I have seen similar questions and the answers on here have resembled the code I have so I am confused. I am checking my logs and it is not descriptive it is just repeating the same message.
The log messages I am receiving in firebase functions is,
Detailed stack trace: Error: Cannot find module '#google-cloud/logging'
If you want to use a module, you have to install it first before you deploy. From your functions folder, where the original package.json exists:
npm install #google-cloud/logging

Gulp location of unhandled error in events.js:141

When I run task for example using comman gulp scripts:common, I get this output:
[14:05:47] Requiring external module babel-core/register
[14:05:49] Using gulpfile /home/sites/blablabla/gulpfile.babel.js
[14:05:49] Starting 'scripts:common'...
events.js:141
throw er; // Unhandled 'error' event
^
SyntaxError: Unexpected token
Well, for SyntaxError it would be useful to know where it found that unexpected token. How to tell it to show at least file and line? Where to find that evetns.js file? Could I put console.trace() or something like that there?
I solve this problem by running jshint on my scripts:
/*
* `gulp check_scripts` - Lints script files
*/
gulp.task('check_scripts', function() {
return gulp.src([
'gulpfile.js' //, other scripts to check
])
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'))
.pipe(gulpif(enabled.failJSHint, jshint.reporter('fail')));
});
enabled.failJSHint is there to allow errors to pass in local environment but fail in production.
This will lint any syntax errors in your scripts.
Additionally you may want to hook it to other task so it's run automatically before proper build:
gulp.task('default', ['check_scripts', 'clean'], function() {
gulp.start('build');
});
This is the general idea.
You can look at error stack trace by adding custom "on error" handler to the gulp task.
gulp.task('compile:js', function() {
return (
gulp.src(jsPath)
.pipe(yourCustomTask())
.on('error', function(err) {
console.log(err.stack);
this.end();
})
);
});
Also, as another variant, adding gulp-plumber into pipeline makes error messages more clear.

Logging with grunt and qunit

I am running javascript unittests with grunt/qunit. Sometimes the tests fails because of e.g syntax errors in the source files (works fine with file info if syntax errors are introduced in the test files). When that happens grunt simply prints the line number and not the file where the problem is.
Running "qunit:all" (qunit) task
Warning: Line 99: Unexpected identifier Use --force to continue.
Aborted due to warnings.
This does not help much since I have 100 of js files. I have looked into:
https://github.com/gruntjs/grunt-contrib-qunit
and tried to add the following to my Gruntfile.js (grunt.event.on):
module.exports = function(grunt) {
"use:strict";
var reportDir = "output/reports/"+(new Date()).getTime().toString();
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
qunit: {
options: {
'--web-security': 'no',
coverage: {
src: ['../src/**/*.js'],
instrumentedFiles: 'output/instrument/',
htmlReport: 'output/coverage',
coberturaReport: 'output/',
linesTresholdPct: 85
}
},
all: ["testsSuites.html"]
}
});
// Has no effect
grunt.event.on('qunit.error.onError', function (msg, stack) {
grunt.util._.each(stack, function (entry) {
grunt.log.writeln(entry.file + ':' + entry.line);
});
grunt.warn(msg);
});
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.registerTask('test', ['qunit']);
Where testsSuites.html contains:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="qunit/qunit.css">
<script src="qunit/qunit.js"></script>
<script src="sinonjs/sinon-1.7.3.js"></script>
<script src="sinonjs/sinon-qunit-1.0.0.js"></script>
<!-- Sources -->
<script src="../src/sample.js"></script>
<!-- Test-->
<script src="test/sample-test.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
</script>
</body>
</html>
But the source file where the problem is located is still not printed. Is is out of Grunts hands to verify source code/show line number/file where e.g a syntax error is located?
I have also tried running:
grunt test --debug 9
It prints some debug info but not any information regarding syntax errors in the javascript sources.
I have tried to install JSHint and call it on all my javascript source files:
for i in $(find ../src -iname "*.js"); do jshint $i; done
Now I get tons of errors but Grunt is still happy. If I introduce a simple syntax error e.g:
(function(){
var sampleVar 32;
}
to provoke an error in Grunt:
Running "qunit:all" (qunit) task
Warning: Line 2: Unexpected number Use --force to continue.
Aborted due to warnings.
it simply disappears in the stream of errors generated by JSHint. How do I filter JSHint "warnings" from critical errors that will actually make Grunt fail?
Or is it qunit that should be configured for more verbose output?
grunt-contrib-qunit will display filenames when encountering a syntax error. Take this simplified version of your Gruntfile.js:
module.exports = function(grunt) {
"use:strict";
grunt.initConfig({
qunit: {
options: { '--web-security': 'no' },
all: ["testsSuites.html"]
}
});
grunt.loadNpmTasks('grunt-contrib-qunit');
};
Running it gives the error you're looking for:
$ grunt qunit
Running "qunit:all" (qunit) task
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2
Warning: 1/2 assertions failed (17ms) Use --force to continue.
Aborted due to warnings.
The issue you're having looks to be a bug(?) in grunt-qunit-istanbul. The warning you're getting:
Warning: Line 99: Unexpected identifier Use --force to continue.
is Grunt handling an uncaught exception. The exception is being raised by the grunt-qunit-istanbul task. You can prove it by modifying this line in your original Gruntfile.js from:
src: ['../src/**/*.js'],
to:
src: ['../src/**/*.js.nomatch'],
This will prevent grunt-qunit-istanbul from finding and parsing any Javascript files before Qunit is run. If you let Qunit run, its error handler prints out the filenames with syntax errors like you want.
The only fix is the workaround I've described, or to patch grunt-qunit-istanbul to add an error handler for parse errors like Qunit does.
Patching grunt-qunit-istanbul
The function that is throwing the exception is Instrumenter.instrumentSync, which it is supposed to do:
instrumentSync ( code, filename )
Defined in lib/instrumenter.js:380
synchronous instrumentation method. Throws when illegal code is passed to it
You can fix it by wrapping the function call:
diff -r 14008db115ff node_modules/grunt-qunit-istanbul/tasks/qunit.js
--- a/node_modules/grunt-qunit-istanbul/tasks/qunit.js Tue Feb 25 12:14:48 2014 -0500
+++ b/node_modules/grunt-qunit-istanbul/tasks/qunit.js Tue Feb 25 12:19:58 2014 -0500
## -209,7 +209,11 ##
// instrument the files that should be processed by istanbul
if (options.coverage && options.coverage.instrumentedFiles) {
- instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+ try {
+ instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+ } catch (e) {
+ grunt.log.error(filepath + ': ' + e);
+ }
}
cb();
Then the test will keep running (and inform you of the syntax error):
$ grunt qunit
Running "qunit:all" (qunit) task
>> /tmp/src/sample.js: Error: Line 2: Unexpected number
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2
Warning: 1/2 assertions failed (19ms) Use --force to continue.
Aborted due to warnings.
I have used grunt-contrib-qunit in the past but I have never attempted something like this. The problem you are facing is fairly interesting because the docs mention that the event qunit.error.onError should be emitted by grunt but it is not happening for you.
I created a new project using a jquery template and changed the code so that my test would fail. After that I wrote the following code:
grunt.event.on('qunit.error.onError', function(message, stackTrace) {
grunt.file.write('log/qunit-error.log', message);
});
When I ran the command grunt, I received no output in the file. To check this, I made a change to the event:
grunt.event.on('qunit.log', function(result, actual, expected, message, source) {
grunt.file.write('log/qunit-error.log', message);
});
Now, this piece of code did give me the error message in my file but it was useless because I could not get the stacktrace or the exact error message.
After this, I though of reading up the source and this is what I found:
phantomjs.on('error.onError', function (msg, stackTrace) {
grunt.event.emit('qunit.error.onError', msg, stackTrace);
});
The grunt event is only emitted when phantomjs throws an error.
At the moment I am not sure how I can get a phantomjs error while testing a simple JavaScript file without any browser related testing. This is my analysis so far and I hope this helps you in someway.

Categories

Resources