I've recently introduced commander.js to a project and use it in various scripts to parse CLI arguments. I'll give one example of where it's been used:
const { program } = require('commander');
program
.description('Import customers and accounts')
.argument('[filePath]', 'Path to JSON file containing customers and accounts', `${path.resolve(__dirname)}/data/customers.json`)
.action(filePath => {
importCustomersAndAccounts(filePath)
.catch((e) => {
console.log(e);
process.exit();
})
.finally(() => process.exit());
})
program.parse();
This script itself isn't the issue, it works fine when run from the CLI. The issue happens when I run tests that use this same script. I have the test script setup in package.json as follows:
"test": "NODE_ENV=TESTING mocha --exit --require tests/setup.js 'tests/src/**/*.spec.js' 'tests/scripts/**/*.spec.js'"
When I run the tests, I immediately get this error:
error: unknown option '--exit'
Which is being thrown by commander, not mocha. So this option getting passed to mocha when running npm run test is getting to the script itself. I've confirmed this is what's happening, because when I chained .option('--exit') after the .description() in the commander code above, it then failed with
error: unknown option '--require'
So it's reaching the next option passed to mocha and then failing on whichever option is not defined in the script. How can I prevent these options from reaching the script itself and get them to simply be parsed by mocha?
Related
I am working on a Docker Swarm data visualization tool with a team.
It works as follows:
Our backend is set up in a way that terminal commands can be executed from our code, where these terminal commands have been promisified and the result of this command should be a string of nodeIDs corresponding to the active nodes in my Docker Swarm. This data is then passed to another helper function, however, I am unable to move past the previously explained step due to an unexpected output from my promisified terminal command.
const getNodeIDs = () => {
console.log('in nodeID helper function');
return execProm("docker node ls --format '{{json .ID}}'").then(
(rawNodeIDs) => {
console.log('rawNodeIds: ', rawNodeIDs);
const parsedNodeIDs = parseRawData(rawNodeIDs);
console.log('parsedNodeIDs: ', parsedNodeIDs);
return parsedNodeIDs;
}
);
};
My code fails on line 6 due to the fact that the data being passed to my parseRawData function is not what it is expected. The console log on line 5 above returns as follows:
{
stdout: 'Saved file tree to doc-filelist.js\n' +
'Copied JS to doc-script.js\n' +
'Compiled CSS to doc-style.css\n',
stderr: ''
}
In addition to this being the wrong output, every time I invoke this command, a new file is created in my codebase labeled "docs" with the following three files inside: doc-filelist.js, doc-script.js, doc-style.css. I am working in a team of 4 other engineers, and I seem to be the only person experiencing this behavior. When I attempt to run the terminal command (featured on line 3 in the first block of code) directly in the terminal itself, I receive the expected output of
"odwch32vsynhxbc0ia2nwicag"
which is the nodeID of the single node currently in my Docker Swarm and what I should be receiving when invoking the terminal command from the code.
I've only been able to find one other stack overflow article dealing with the same issue in which that person was told to try running the terminal command
npm uninstall -g docker
which I have done, and this did not fix my issues. I've also looked into making edits to the Docker daemon itself, but am unsure that this is the real root of the issue. Since I am the only person on my team that seems to be encountering this bug, I have reason to believe that this error has something to do with my dev environment. My containers are running on Docker v4.15.0 and I am working on macOS on an M1 chip computer.
Thanks!
I run Windows10, I have a project made on Cypress and I want to log the test results both on a file AND on console: I tried just printing on a file, using in my package.json this script:
"scripts": {
"open": "./node_modules/.bin/cypress open",
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' > cypresstest.log"
}
And this runs smoothly; my issue is that there are more than 100 tests and it takes very long time (like 20 minutes); so I can't check if something got frozen or is working fine, because nothing is printed on console.
So I tried with
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' | tee cypresstest.log"
But since I'm on windows, it says
tee is not recognized as internal or external program
Is there a way, or a plugin, or something I can do to simply print both on console AND on a file log?
Cypress-terminal-report has such a feature, or you can use a custom command including cy. task instead of cy.log - for example:
cypress plugin file
module.exports = (on, config) => {
on('task', {
log (message) {
console.log(message)
return null
}
})
}
custom command:
Cypress.Commands.add("logInAndOut", (message) => {
cy.log(message)
cy.task('log', message)
});
test file
cy.logInAndOut('My log')
Edit: I found another solution - Commands. overwrite(), and I`ll list an example, but I do not recommend it, since if other people try to use the code after you - won't know the change:
Cypress.Commands.overwrite('log', (originalFn, message, args...) => {
console.log(message, args...)
// originalFn is the existing `log` command that you need to call
// and it will receive whatever you pass in here.
//
// make sure to add a return here!
return originalFn(message, args...)
})
I have error in the following below test. My node version is : v12.10.0. is there any alternative of setTimeout?
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
The Error log is as
Call retries were exceeded
at ChildProcessWorker.initialize (../../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:230:21)
just add jest.useFakeTimers(); after your imports
...
jest.useFakeTimers();
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
it works in my code
In my case, the actual problem was with the promise handling.
I got the same issue when I was running all my test cases in one go with the jest.
Solution:
Try running one test separately then see what error is coming.
I got the below error after running one problematic test separately where earlier I was getting the Call retries were exceeded:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read property 'code' of undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
With this, I was sure that the problem is with the catch block and when I added it in the async service API function then the test case worked perfectly fine.
Maybe you can also try the same and see if it works for you or not.
I am using the below config:
node: 15.13.0
npm: 7.8.0
jest: 26.6.3
Try running npm doctor using the latest npm version. It's a great tool and it helped me diagnose permission and ownership issues right away.
Takeaway:
Verify File/Folder Permissions & Ownership
Encountered same error when updating the vue-jest version to below listed versions
#vue/vue3-jest: ^27.0.0-alpha.4
#vue/cli-plugin-unit-jest: ~5.0.0,
node: v17.9.0 or v16.14.2
Error disappeared, once downgraded it to node version v14.x.x
Hunch is - the latest node versions are not compatible with the dependencies.
I was able to run the test's successfully doing the following;
Install npm i -D jest-canvas-mock
Update the jest.config.ts file to have:
export default {
...
testEnvironment: "jsdom",
setupFiles: ["jest-canvas-mock"],
}
I have developed a node application which I would like to have called as an AWS Lambda Application.
The application works as intended as an AWS Lambda, however my CloudWatch logs always finish with the following error: Process exited before completing request.
I wrote some code to ensure that my context.succeed() and context.fail() calls were taking place and they are. However, when ran locally, I also noted a lag between my logging of success in start.js and the command prompt appearing again, making me believe there could be some node processes still taking place once those calls have been made. Could that be causing the error, and if so what is a good way to triage and resolve the issue?
The relevant code is below:
lambda-handle.js
import log from './log';
import database from './database';
import User from './database/models/user';
export function handle(event, context) {
log.info('CS Blogs Feed Aggregator Started');
database.sync()
.then(() =>
User.findAll({
attributes: ['id', 'blogFeedURI']
}))
.then(users => {
users.forEach(user => {
log.info({ user }, 'User loaded from database');
});
})
.then(() => {
// context.done() called so AWS knows function completed successfully
context.succeed();
})
.catch(error => {
context.fail(error);
});
}
start.js (used to test context.succeed/fail being called)
// This function invokes the AWS Lambda Handle as AWS would
// but allows you to do it from your local machine for development
// or from a non-AWS server
import { handle } from './lambda-handle';
import log from './log';
handle({}, {
succeed: result => {
log.info({ result: result || 'No result returned' }, 'Process succeeded');
},
fail: error => {
log.error({ error: error || 'No error returned' }, 'Process failed');
}
});
The code is being transpiled by babel before being deployed. However, I suspect there is more of a logic issue so I have shown you the original source code.
If any more information is required the repository is available here: https://github.com/csblogs/feed-downloader/tree/fix/lambda-implementation-details
Thanks
I am pretty sure this is caused by at least 1 native module dependency in bunyan(dtrace-provider). Native modules need to be built/installed on the system that they will run on. So in the case of Lambda you need to run npm install on a linux ec2 instance or possibly vagrant to get the right version of dtrace-provider built.
See:
Cross-compile node module with native bindings with node-gyp
https://aws.amazon.com/blogs/compute/nodejs-packages-in-lambda/ (scroll to Native Modules)
You could probably just remove Bunyan to verify it works and then go down the ec2/vagrant compile route if that fixes it.
I have two javascript files which contain mocha test cases.
//----------abc.js -------------
describe("abc file", function(){
it("test 1" , function(){
assert.equal(20 , 20);
});
});
//---------xyz.js--------------
describe("xyz file", function(){
it("test 1" , function(){
assert.equal(10 , 10);
});
});
I have put them in a folder called test and when I execute the mocha command the first file(abc.js) is always executed before xyz.js.
I thought this might be due to alphabetical ordering and renamed the files as
abc.js => xyz.js
xyz.js => abc.js
but still, the content of the xyz.js (previously abc.js) is executed first. How can I change the execution order of these test files?
In the second file, require the first one:
--- two.js ---
require("./one")
or if you are using ES modules:
--- two.js ---
import "./one"
Mocha will run the tests in the order the describe calls execute.
I follow a totally seperate solution for this.
Put all your tests in a folder named test/ and
Create a file tests.js in the root directory in the order of execution
--- tests.js ---
require('./test/one.js')
require('./test/two.js')
require('./test/three.js')
And in the tests files one.js, two.js and so on write your simple mocha tests
this way if you want to run them in the order you have defined then just run mocha tests.js
Mocha has a --sort (short -S) option that sorts test files:
$ mocha --help
[...]
-S, --sort sort test files
[...]
Since mocha sorts files in alphabetical order, I usually prefix my test files names with numbers, like:
0 - util.js
1 - something low level.js
2 - something more interesting.js
etc.
In addition to being really easy to maintain (no gulp grunt or any of that nonsense, no editing your package.json...), it provides the benefit that:
people reading your source code get an idea of the structure of your program, starting from the less interesting parts and moving up to the business layer
when a test fails, you have some indication of causality (if something failed in 1 - something.js but there are no failures in 0 - base.js then it's probably the fault of the layer covered by 1 - something.js
If you're doing real unit tests of course order should not matter, but I'm rarely able to go with unit tests all the way.
If you prefer a particular order, you can list the files (in order) as command-line arguments to mocha, e.g.:
$ mocha test/test-file-1.js test/test-file-2.js
To avoid a lot of typing every time you want to run it, you could turn this into an npm script in your package.json:
{
// ...
"scripts": {
"test": "mocha test/test-file-1.js test/test-file-2.js"
}
// ...
}
Then run your suite from the command line:
$ npm test
Or if you're using Gulp, you could create a task in your gulpfile.js:
var gulp = require('gulp');
var mocha = require("gulp-mocha");
gulp.task("test", function() {
return gulp.src([
"./test/test-file-1.js",
"./test/test-file-2.js"
])
.pipe(mocha());
});
Then run $ gulp test.
The way it worked for my tests to be executed in a specific order was to create a separate test.js file and then added a describe for each mocha test file I'd wanted to execute.
test.js:
describe('test file 1', function() {
require('./test1.js')
})
describe('test file 2', function() {
require('./test2.js')
})
Then simply run mocha test.js
I am exporting an array with all required files and that is the way I tell mocha the order of execution through index.js file in the folder with all my test files:
const Login = require('../login');
const ChangeBudgetUnit = require('./changeBudgetUnit');
const AddItemsInCart = require('./addItemsInCart');
// if the order matters should export array, not object
module.exports = [
Login,
ChangeBudgetUnit,
AddItemsInCart
];
mocha-steps allows you to write tests that run in a specific sequence, aborting the run at the first failure. It provides a drop-in replacement for it, called steps.
Example usage:
describe('my smoke test', async () => {
step('login', async () => {})
step('buy an item', async () => throw new Error('failed'))
step('check my balance', async () => {})
xstep('temporarily ignored', async () => {})
})
The repo hasn't seen much activity in three years, but it works fine with Mocha 9.