How to Mock non-existent file import in nodejs Lambda - node.js

I am facing issue in testing where My logger is in lambda layer thus non-existing for nodeJs import in lambda.js during mocha-chai testing. I tried mock-fs but getting errors Can not find module /opt/logger.js or maybe I am trying wrong way and not sure if it is useful in this way. Please check below code for reference. Any help or suggestion is most welcome.
lambda.js -
const logger = require('/opt/logger.js') // coming from lambda_layer.js
lambda.test.js -
mock({
"/opt/logger.js": console.log('hello')
});

Was able to accomplish this with mockery. Thanks for allowing me to put this here for everyone. Will update this with better code soon.
mockery.registerMock({'/test/': { destroyAllHumans: actionStub })
mockery.enabled();

Related

console.log() not appearing in output for express server

I can't for the life of me figure out how to get console.log() to appear with my express server. It's a middle-tier API for our front-end. You'll have to forgive me if I speak about it a little awkwardly, I'm relatively inexperienced with these tools but I'll do my best to explain the issue despite my inexperience. I'm trying to use console.log to get a better idea of a rather complex projects behavior and what might be causing some issues with it in its current state. Unfortunately console.log only seems to work within plainjane examples like so:
export const routerExample = express.Router();
routerExample.use((req, res, next) => {
console.log('Time: ', Date.now()); // I show up in console just fine
next();
});
When I try to lookup the problem I'm experiencing all solutions seem to be regarding getting routing examples like the one above to appear in console, I can see such examples just fine. The problem comes from getting anything to show up in examples like:
// routing.ts
import { homeController } from '../controllers/homeController';
const homeEx: HomeExample = new HomeExample();
routerExample.get('/home', homeEx.getHome);
// homeController.ts
export class HomeExample {
public getHome (req: Request, res: Response) : void {
console.log("something is happening");
// do stuff
}
}
Any uses of console.log like above never appear anywhere in node's console (or elsewhere as far as I can tell).
What am I missing that is needed to make these log messages appear? This has to be incredibly simple but I've been through numerous similar sounding issues on stackoverflow and elsewhere and everything single of one of them seems to be describing slightly different issues (or misunderstandings) that don't solve my own issue. I've tried numerous versions of node/npm and have added the DEBUG:* flag as well. None of this seems to solve it. If I'm missing any code that'd help give context to the issue let me know. I've obviously cut down parts and renamed some objects as I can't exactly dump work-related code here. What am I missing? Any help would be greatly appreciated :)
Edit 1: since many similar posts to this seem to get this mixed up, no I'm not looking at my front-end's console or something for the output. I'm looking in the terminal window where I start the server from, where the router example does appear.
Edit 2: for reference, my file structure is something like:
app/
controllers/
homeController.ts (HomeExample stuff is here)
routes
routing.ts (routerExample stuff is here)
app.ts
...
Edit 3: the code works overall to be clear. the problem is explicitly that that log.console() isn't appearing, all the code I've wrapped into "// do stuff" is working as expected.
Checkout Express Middlewares
routerExample.get('/home', homeExample);
function homeExample (req: Request, res: Response, next:NextFunction) : void {
console.log("something is happening");
// do stuff
}
}
You are also calling a member of a non static or instantiated class see this:
TypeScript - Static
What you are missing is to create a new instance of the homeExample class. What I recommend is to export the new instance on the route file like this:
/routes/home.route.js
class HomeRoute {
/* your methods */
}
export default new HomeRoute();
then you can use it:
import homeRoutes from './routes/home.route';
router.get('/home', homeRoutes.getHome);
See the example:
https://replit.com/#abranhe/expressjs-console-log#index.js
After a fresh nights sleep I've figured it out. It, of course, was the most obvious problem that managed to slip by me in the overall complexity of the codebase. The /home call was deprecated and replaced with a different call in the front-end without mention in the middle-tier code that I had posted. I didn't even consider checking what was being called any deeper since I was experiencing the same issue with multiple other calls that I didn't include in the original post for brevity. Basically all the tools I'm working with here are completely new to me so my inexperience got the best of me. Thank you to #jfriend00 who made me double-take how /home was being called (it wasn't).
Since I was getting the data I needed without issue on the front-end I assumed these functions were being run, seeing as the data they produced was the same kind of data that was successfully being shown by the front-end, just without the console.log() output I added appearing.
Moral of the story: if every other question related to an issue on Stack Overflow concludes with "I just made a dumb mistake," take absolutely every precaution possible to observe what's happening, even if you feel like you already ruled out certain possibilities. Unfortunately I got a bit caught up with all the weird solutions I saw to the point where I got ahead of myself in debugging the problem.
I'm still a bit confused since the /home call specifically should still be "active" even if not called by the front-end, but console.log() is clearly working on other similar functions I've tested since figuring this out. There's either something hidden deep in the codebase that's breaking/overwriting /home and other old calls, or it's simply not being called right when I'm testing it outside of the front-end.
TLDR: I'm an idiot, every single API call I thought I was testing was not actually being called. Double-check your assumptions before asking for a specific solution.

React native crypto stream module is undefined

I'm giving a try with [react-native-crypto][1] in order to learn how to convert nodejs to be used in React Native project in the future. Unfortunately, I couldn't get it running successfully. I've faced an issue with stream is undefined. ERROR TypeError: undefined is not an object (evaluating '_$$_REQUIRE(_dependencyMap[0], "stream").Transform.call').
If you have ever faced a similar problem, I'm so grateful for your help.
Also, I attach the screenshot of the issue as the following
For anyone still trying to solve this issue, I have figured out a solution that worked for me. So within node_modules/cipher-base/index.js, the top of the file should have a line which defines the variable Transform as var Transform = require('stream').Transform. For some reason, it does not like the module stream and as such it needs to be changed to readable-stream. Therefore the variable Transform should now read var Transform = require('readable-stream').Transform.
From what I have gathered, the stream module it is trying to refer to isnt actually a module that can be used. The reason why it gets referenced however seems to be because the tsconfig.json file in the root directory specifies "stream": ["./node_modules/readable-stream"] as a path, almost as if to make stream refer to the readable-stream module, which in theory it should refer to when it is called. But in this case it doesnt happen so we need to explicitly define that we are refering to the readable-stream module.
Hope this helps anyone else out there and prevents others scratching their heads for hours on end like it did for me!
I have figured it out by editing in metro.config.js as the following:
resolver: {
extraNodeModules: {
stream: require.resolve('stream-browserify'),
}
},

How requiring a module on entry point makes available on other modules on NodeJS?

This is probably a duplicated question, but I couldn't find anything.
Since I'm learning NodeJS, I think that I'm not using the right words to search, so it's hard to find an answer.
Here is the situation:
I'm currently following an online course about NodeJS and coding an API.
In the current step we are using Winston library to log errors. The instructor, have configured on Index,js, which is the entry point of the app, like this:
File: index.js
const winston = require('winston');
const errorHandler = require(./middleware/error.js);
//(...) some other imports
app.use(errorHandler);
winston.add(winston.transports.File,{filename:'logFile.log'});
And in other module we've created in the course to handle errors, he requires winston and simply call to log the error. Something like this:
File: error.js
const winston = require('winston');
function errorHandler(err,req,res,next){
winston.error(err.message,err);
res.status(500).send("something failed");
}
module.exports = errorHandler;
After doing a test, the error is correctly written to the file, and my question is: How it works? How a setting made on the 'required version' of winston at index.js is visible from the other required version at error.js?
From index.js we are importing error.js too, so i can imagine somehow this two modules are sharing this winston object, but again, I don't understand how or where is it shared.
Again, please excuseme if I'm not using the right terms to refer anything here, I'll accept any advice.
Thanks.
When a module is loaded in node.js, it is cached by the require() sub-system. So, when you then require() it again, that means you'll get the exact same module as the previous one.
So ... if you initialized the module after you first loaded it and the module stores some state that represents that intialization, then subsequent use of that module will be using the same (already initialized) module.
And in other module we've created in the course to handle errors, he requires winston and simply call to log the error.
It gets the same instance of the winston module that was already initialized/configured previously.
After doing a test, the error is correctly written to the file, and my question is: How it works? How a setting made on the 'required version' of winston at index.js is visible from the other required version at error.js?
Module caching as describe above. There's only one winston module that all are sharing so if it's initialized/configured in one place, all will use that configuration.

Encoding not recognized in jest.js

I have a problem testing a project using node-mysql2, react, sequelize and jest. This problem only occurs during testing.
Encoding not recognized: 'cesu8' (searched as: 'cesu8')
at Object.getCodec (project/node_modules/mysql2/node_modules/iconv-lite/lib/index.js:106:23)
at Object.getDecoder (project/node_modules/mysql2/node_modules/iconv-lite/lib/index.js:122:23)
at Object.<anonymous>.exports.decode (project/node_modules/mysql2/lib/parsers/string.js:9:23)
at Packet.Object.<anonymous>.Packet.readNullTerminatedString (project/node_modules/mysql2/lib/packets/packet.js:373:23)
at Function.Object.<anonymous>.Handshake.fromPacket (project/node_modules/mysql2/lib/packets/handshake.js:18:31)
at ClientHandshake.Object.<anonymous>.ClientHandshake.handshakeInit (project/node_modules/mysql2/lib/commands/client_handshake.js:98:38)
at ClientHandshake.Object.<anonymous>.Command.execute (project/node_modules/mysql2/lib/commands/command.js:40:20)
at Connection.Object.<anonymous>.Connection.handlePacket (project/node_modules/mysql2/lib/connection.js:515:28)
at PacketParser.onPacket (project/node_modules/mysql2/lib/connection.js:94:16)
at PacketParser.executeStart (project/node_modules/mysql2/lib/packet_parser.js:77:14)
at Socket.<anonymous> (project/node_modules/mysql2/lib/connection.js:102:29)
This is problem caused by mysql2 doing dynamic lazy require of encodings and Jest not being able to handle this. Have a look at few workarounds users suggested here:
add this snippet to setupTestFrameworkScriptFile
require('mysql2/node_modules/iconv-lite').encodingExists('foo');
or this somewhere early to your code:
import iconv from 'iconv-lite';
import encodings from 'iconv-lite/encodings';
iconv.encodings = encodings;
Really only need to add:
require('iconv-lite').encodingExists('foo')
to the top of whatever file you're testing such as factory.test.js
Not sure why this is unfortunately, but the above is better for copy / pasting than the chosen answer.
In my case, the encoding error appeared after a ReferenceError
The cause was a test calling a method that was making an async database call via mysql2 for which I had forgotten to await.
The solution for me was to simply add await in the right place.
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From models/alert.test.js.
at Object.getCodec (node_modules/mysql2/node_modules/iconv-lite/lib/index.js:63:27)
at Object.getDecoder (node_modules/mysql2/node_modules/iconv-lite/lib/index.js:125:23)
at Object.<anonymous>.exports.decode (node_modules/mysql2/lib/parsers/string.js:10:25)
at Packet.readNullTerminatedString (node_modules/mysql2/lib/packets/packet.js:412:25)
at Function.fromPacket (node_modules/mysql2/lib/packets/handshake.js:62:33) ^
...
Error: Encoding not recognized: 'cesu8' (searched as: 'cesu8')
at Object.getCodec (/Users/.../node_modules/mysql2/node_modules/iconv-lite/lib/index.js:104:23)
I met a similar issue with network node module. I made a workaround by mocking the network module and not using the iconv-lite. The following is my code.
jest.mock('network', () => ({
get_active_interface: cb => {
cb?.(undefined, { type: 'Wired' });
},
}));
As for this case, maybe you could try mock the module that made the call, some code like this.
jest.mock('mysql2',()=>({
someFuncThatCallsIcoveLite:(..._)=>{}
}))
require('../../node_modules/mysql2/node_modules/iconv-lite/lib').encodingExists('foo');
This worked for me on
Node 16.17.1
ts 4.8.4
jest 29.2.2

node.js http.connections

I am looking over node.js code and can't understand some of it. Please help me with it.
var http = require("http"),
server = http.createServer(function(req,res) {});
......
if(MaxUserCheck <1 ){
server.watcher.stop();
logmsg(level1, server.connections);
}
For the above code,
what is "watcher" and how to use it?
"server.connections" - what is this? and how to use it?
I have seen using server module as
server.on('request', function (req,res){};
...
server.listen(52273, function(){};
and I can understand as above, but using as "server.connections" can't understand and haven't seen it use like that.
I looked up on node.js manual but doesn't explain it.(http://nodejs.org/api/)
It seems that "server.connections" returns how many clients connected to our server..(Server uses Fugue for multi clients)
where can I find the usage of "server.connections" and "server.watcher"
Thank you.
These two syntaxes might have been used/required in other directories. If I export this module to a different file and say require('watcher') there , it will work.however I'm not sure what watcher is used but it could be webwatcher module.

Resources