Is there a way to mock `module` variable? - node.js

I want to test my app init function, that depends on node.js module variable (webpack's module variable to be precise). I can't pass module variable as a function parameter because of this webpack GitHub issue.
I found this rewire library, that seems to be good for my problem. But it looks like it is abandoned and has some errors because of my ES6 imports.
Code sample I want to test:
import ReactDOM from 'react-dom'
import React from 'react'
import Root from './components/Root'
export function init() {
const {AppContainer} = require('react-hot-loader')
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById('root')
)
}
render(Root)
if (module.hot) { // the part I would like to test by mocking `module` variable
module.hot.accept('./components/Root', () => { render(Root) })
}
}
init()

Related

How to use Winston Logger in NestJS separate module that doesn't use Classes

I've tried a few different ways of doing this.
I can't set Winston as the default logger for NestJS at the moment because it complains about "getTimestamp" function not being in the instance.
So - for controllers in NestJS - I have used dependency injection - which works fine for the api ( REST endpoints ).
The problem is that I have moved away from OOP - so all of my libraries are written in typescript as functions. Not pure functions but better than an OOP approach ( many less bugs! )
My question is - how do I get access to the main winston logger within my libraries that don't have classes.
I am using the library nest-winston.
Have you tried this?
create the logger outside of the application lifecycle, using the createLogger function, and pass it to NestFactory.create (nest-winston docs)
You can have a separate file that creates the logging instance, then import that into your modules/libraries as well as import it into your main.ts
// src/logger/index.ts
import { WinstonModule } from 'nest-winston';
export const myLogger = WinstonModule.createLogger({
// options (same as WinstonModule.forRoot() options)
})
// src/myLib/index.ts
import { myLogger } from '#/logger' // I like using aliases
export const myLib = () => {
// ...
myLogger.log('Yay')
}
// src/main.ts
import { myLogger } from '#/logger'
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: myLogger
});
}
bootstrap();

export/import javascript class like module node into electron with webpack

In context of basic electon-vue app, I want to create my own javascript class and use it into main process or renderer or into vue component.
I created JS Class but I never find a good way for exporting my class.
All possibility of writing import/export module find in the web finished by same error : Undefined exports
"use strict"
import fs from 'fs'
import typeorm from 'typeorm'
import Public from './../entity/Public'
class ConnectionManager
{
constructor(){}
getConnection(type, name, options) {
}
}
module.exports = ConnectionManager
But it seeams that others js file work perfectly like the vue-router js for routing into vue.js app :
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: require('#/components/Home').default
}
]
})
I package my code with Webpack and libraryTarget Output is : commonjs2
I seems that use babel-loader with webpack
node version : 10.13.0
electron : 3.0.10
Babel : 6
EDIT :
I try this syntax class js file :
"use strict"
import * as fs from 'fs'
import * as typeorm from 'typeorm'
import {Public} from './../entity/Public'
export default class ConnectionManager
{
constructor(){}
getConnection(type, name, options) {
}
}
with this import syntax :
import ConnectionManager from './../service/connectionManager'
But I have this error when I execute code into electron :
Uncaught TypeError:
_service_connectionManager__WEBPACK_IMPORTED_MODULE_8__.default.getConnection
is not a function
I console logged this service class "ConnectionManager" and I have this result (so it really exist) :
ƒ ConnectionManager() {
babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0___default()(this, ConnectionManager);
}
It seems that the final js module webpack contain the ConnectionManager class
It seems that you mix commonjs modules with ES modules by the wrong way.
There are a lot of modules (include node built-in) which have no default export. To import such a module you need to use * as moduleAlias or { exportedField } in your import statement. Try to rewrite your code by this way:
import * as fs from 'fs'
import * as typeorm from 'typeorm'
import { Public } from '../entity/Public'
export default class ConnectionManager
{
constructor(){}
getConnection(type, name, options) {
}
}
Because this class is exported as a default value, you can use the following construction to import it as a default field, where ConnectionManager is an alias for the current scope:
import ConnectionManager from '../service/connectionManager'

Import Module in ES6 Class Function

I have migrated my project to ESM and thus using .mjs in all my files in nodejs.
Previously in CommonJs, I could require a file right in the middle of a ES6 class function in order to load it only when needed.
module.exports = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
const module = require('module')
//use required file/module here
}
}
But now when using Michael Jackson Scripts a.k.a .mjs, I cannot import a file on demand:
import Koa from 'koa'
export default = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
import module from 'module'
//use imported file/module here
}
}
My app has many files/modules that are not consumed immediately, and can more can always be added in future, thus hardcoding the imports at the begining of the file is not an option.
Is there a way to import the files dynamically on demand when needed?
With a little modification from this answer, I managed to get it working via:
import Koa from 'koa'
export default = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
const router = await import('./Router')
//use imported file/module here
}
}
Or you can use a promise if you are into that:
import('./router')
.then(something => {
//use imported module here
});
This suits me for now until the spec if finalised and shipped

How to export and use multiple custom modules in the same library with React Native

So I have a React Native custom library that I made that has 2 modules made, moduleA and moduleB. How do I export them so that I can call both of the modules in my project?
Before when I had only one module it would work perfectly like this:
//Index.js file of my library
import { NativeModules } from 'react-native';
const { moduleA } = NativeModules;
export default moduleA;
and then in my React native project I could call it like this
//Home.js file of my project
import moduleA from 'custom_library';
moduleA.method(); //Works fine
But now that I have two modules, I'm not sure how to change the modules and the import such that both can be used. Is it even possible? The end goal that I want to be able to do is
//Home.js file of my project
import { moduleA, moduleB } from 'custom_library';
moduleA.method();
moduleB.method();
Sorry for the basic question, but I'm getting frustrated that nothing I've tried is really working.
Just use the export keyword. You will find more detailed examples here.
index.js of custom_library
import { NativeModules } from 'react-native';
const { moduleA, moduleB } = NativeModules;
export { moduleA, moduleB };
home.js
import { moduleA, moduleB } from 'custom_library';
moduleA.method();
moduleB.method();

Error while creating a npm module of a react component

I am trying to create a node module for all the reusable react components that i have. I am stuck while importing a jsx file.
I have a basic jsx module i.e greeting.jsx in components folder.
//greeting.jsx
import React from 'react';
export default class Greeting extends React.Component {
render() {
return (
<p>Hello World</p>
)
}
}
Folder structure :-
- index.js
- components
¦-- Greeting
¦-- greeting.jsx
¦-- <Other Modules like Greeting>
index.js which imports all the components and exports them
//index.js
import Greeting from './components/Greeting/greeting.jsx';
export default {
Greeting
};
When i have to use greeting module i have to import the module. Like the way in below code. But doing this gives me error on the page
import React from 'react';
import ReactDOM from 'react-dom';
import GreetingModule from './index.js';
ReactDOM.render( <GreetingModule />, document.getElementById('content') );
Errors:-
warning.js:45 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).
invariant.js:39 Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
This is where i am stuck now. Although if i import jsx file directly (like below) then it works.
import React from 'react';
import ReactDOM from 'react-dom';
import GreetingModule from './components/Greeting/greeting.jsx';
ReactDOM.render( <GreetingModule />, document.getElementById('content') );
But this is not the way i want to do as i am trying to create a npm module and my index.js should export all the react components.
I have tried googling for creating a npm module for react componets but couldn't find any thing. Please Help, in resolving the issue
The problem is that you are running a babel transform on module in isolation.
I bet that your index.js after transform looks something like:
var Greeting = require('./components/Greeting/greeting.jsx');
exports.default = {
Greeting
};
And here lies the problem. Your module is exporting all its meat under the default property. So a person using your module needs to use it as follows:
var Greeting = require('greeting').default;
You may either live with this, or use the old way of exporting modules in your index.js. So, you'd change only your index.js to this:
//index.js
import Greeting from './components/Greeting/greeting.jsx';
module.exports = {
Greeting
};
That should do the trick.

Resources