how to require connect-mongo(session) in our code - express

when i write
const MongoStore = require('connect-mongo')(session);
lise it's through an error
ERROR:--
TypeError: Class constructor MongoStore cannot be invoked without 'new'
how i solve the problem

Related

How to mock vuex functions with no direct access?

So I have run into quite a test problem.
To Summarize:
A while back I created a private npm Module, that manages and create a vuex store and injects it as a module into the main vuex store.
Now I want to mock a specific function of that vuex module in my test but that doesn't work.
I tried this:
store.getters.getSomething = jest.fn(() => "stuff);
But that results in this error:
TypeError: Cannot set property getSomething of #<Object> which has only a getter
Now did a little digging, and I here you can see where this getter comes from:
First there is a simple vuex module definition:
//vuexModule this is not accessible outside of the npm module
getters:{
getSomething: (state)=>{ return "stuff"}
}
export { getters }
Now this is imported into this class:
//storeProvider //this is exposed by the npm package
import vuexModule from "./vuexModule";
export default class StoreProvider {
constructor(vuexStore, vuexModuleName = "someStore") {
this.vuexStore = vuexStore;
this.vuexStore.registerModule(vuexModuleName, VuexConfigStore);
}
So this class will generate a vuex module using the previously defined module.
Now the whole thing is added to the main vuex store in the actual application.
Note: this code is now the actual application and not in the npm package.
import StoreProvider from "someNpmModule";
import mainStore from "vuexPlugin";
const storeProvider = new StoreProvider(store);
//later in main:
new Vue({ mainStore })
So the question is: How can I mock getSomething?
I know the code is quite abstracted, but I can't show all the code, and its probably too much for stackoverflow.
The main point is, that I can just import the getter and mock it like this:
import {getSomething} from "...";
getSomething = jest.fn(() => "stuff);
//Or this:
store.getters.getSomething = jest.fn(() => "stuff);
I found this stackoverflow question: TypeError during Jest's spyOn: Cannot set property getRequest of #<Object> which has only a getter
But as the npm package is rather big I can't just mock the whole package for the unit tests, as it provides some necessary pre-conditions. I tried genMockFromModule(), but I still need to target this specific function.
And as mentioned I can't simply import the function.
Any ideas?

Argument of type 'Session | undefined' is not assignable to parameter of type 'Session'

Here's a simplified version of my code:
npm install express express-cookies #types/cookie-session #types/express-session
import express from express();
import cookieSession from 'cookie-session';
const app = express();
app.use(cookieSession({
name: 'session',
keys: [
process.env.SESSION_KEY as string
]
}));
const router = express.Router();
const changeSession = (session = express.Session) => {
session.foo = 'bar'
}
router.get((req, res) => {
changeSession(req.session)
});
On changeSession(req.session) I get the error:
Argument of type 'Session | undefined' is not assignable to parameter of type 'Session'.
Type 'undefined' is not assignable to type 'Session'
Same happens when I use app.get instead of router.get
Not sure why express-cookies isn't registering the session object to the request properly.
Here's a link to #types/cookie-session: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/cookie-session/index.d.ts which provides typings for express-cookies
Any help?
The express-cookies typings specify that req.session can be undefined. As I understand, req.session will be defined only if you register the cookieSession middleware with express. So, if for any reason you won't register this middleware (e.g., delete the code which registers it by mistake), req.session will be undefined.
Because there is a possibility that the session middleware may not be registered, type-wise it is correct to expect that req.session may be undefined.
So, using TS you would need to check if req.session is defined before working with it:
if (req.session) {
changeSession(req.session)
}
Or throw an error explicitly if the session is mandatory for a route:
if (!req.session) {
throw new Error('Session is missing.');
}
changeSession(req.session)
Or as last resort, use the exclamation mark to tell TS that req.session is actually defined:
changeSession(req.session!)
But this won't be type-safe.
The error is quite explicit, express.Session may be undefined and the changeSession function is declared to expect a parameter of type Session (not Session | undefined).
If you are sure your express.Session object won't be undefined, you can assign the default parameter value like so
const changeSession = (session = express.Session!) => {
session.foo = 'bar'
}
Notice the exclamation mark (!) after the value. It forces the compiler to forget about undefined values.
This is quite tricky and, of course, you could end having runtime exceptions if this express.Session is undefined.
Hope it helps.

How to disable the "Global error handler detected" warning in vue test utils

I'm creating async tests using vue-test-utils and jest using the approach described here:
https://vue-test-utils.vuejs.org/guides/#what-about-nexttick
where you set Vue.config.errorHandler = done like shown below
test('Then we are shown events in EventCreate component', done => {
Vue.config.errorHandler = done
This is working and when an error is thrown in a promise handler in a component my tests will fail. However I'm getting this warning.
console.error node_modules/#vue/test-utils/dist/vue-test-utils.js:1421
[vue-test-utils]: Global error handler detected (Vue.config.errorHandler).
Vue Test Utils sets a custom error handler to throw errors thrown by instances. If you want this behavior in your tests, you must remove the global error handler.
I don't want to spam my test output with this warning. Is there a way to disable it?
This is how I did
beforeEach(() => {
jest.spyOn(console, 'error');
console.error.mockImplementation(() => 'some error');
});
afterEach(() => {
console.error.mockRestore();
});

Testing: mocking node-fetch dependency that it is used in a class method

I have the following situation:
A.js
import fetch from 'node-fetch'
import httpClient from './myClient/httpClient'
export default class{
async init(){
const response = await fetch('some_url')
return httpClient.init(response.payload)
}
}
A_spec.js
import test from 'ava'
import sinon from 'sinon'
import fetch from 'node-fetch'
import httpClient from './myClient/httpClient'
import A from './src/A'
test('a async test', async (t) => {
const instance = new A()
const stubbedHttpInit = sinon.stub(httpClient, 'init')
sinon.stub(fetch).returns(Promise.resolve({payload: 'data'})) //this doesn't work
await instance.init()
t.true(stubbedHttpInit.init.calledWith('data'))
})
My idea it's check if the httpClient's init method has been called using the payload obtained in a fetch request.
My question is: How I can mock the fetch dependency for stub the returned value when i test the A's init method?
Finally I resolved this problem stubbing the fetch.Promise reference like this:
sinon.stub(fetch, 'Promise').returns(Promise.resolve(responseObject))
the explanation for this it's that node-fetch have a reference to the native Promise and when you call fetch(), this method returns a fetch.Promise. Check this out
You can stub fetch() as decribed in the manual
import sinon from 'sinon'
import * as fetchModule from 'node-fetch'
import { Response } from 'node-fetch'
// ...
const stub = sinon.stub(fetchModule, 'default')
stub.returns(new Promise((resolve) => resolve(new Response(undefined, { status: 401 }))))
// ...
stub.restore()
Note, that fetch() is the default export from node-fetch so you neeed to stub default.
sinon.stub(fetch) can't stub a function itself. Instead you need to stub the node-fetch dependency from inside ./src/A, perhaps using something like proxyquire:
import proxyquire from 'proxyquire`
const A = proxyquire('./src/A', {
'node-fetch': sinon.stub().returns(Promise.resolve({payload: 'data'}))
})
#mrtnlrsn's answer does not work for files generated from TypeScript in NodeJS, because default is a generated property, each module which imports such a dependency has its own, so stubbing one does not affect others.
However, NodeJS gives access to imported modules, so stubbing works this way:
const nodeFetchPath = require.resolve("node-fetch");
const nodeFetchModule = require.cache[nodeFetchPath];
assert(nodeFetchModule);
const stubNodeFetch = sinon.stub(nodeFetchModule, "exports");
Make sure you use the same node-fetch module as the tested module, e.g. using yarn dedupe. Or build your own nodeFetchPath.
In my case, I found it useful to preserve the node-fetch functionality since my mock responses were already being supplied via nock
To accomplish this, I proxyquire'd the dependency as described in the answer above but wrapped a require call in a spy:
import proxyquire from 'proxyquire'
import { spy } from 'sinon'
const fetchSpy = spy(require('node-fetch'))
const moduleA = proxyquire(
'./moduleA',
{ 'node-fetch': fetchSpy }
)
...
expect(fetchSpy.args).toBe(...)

nodejs - mpromise (mongoose's default promise library) is deprecated

I research many page and i also receive almost advice is add mongoose.Promise = global.Promise; before connection.
This is my code:
var mongo = require('mongodb');
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/mean', function(err, res) {
if (err) {
console.log(err);
}
else {
console.log('Connected to DB');
}
});
The first time program run ok. Data is added to database. But, in the second time, I still get error :
DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
Any help me this problem ?
This is a warning saying that Mongoose's default promise library is deprecated.
You should use third party promise libraries instead e.g. Bluebird or Q.
Here's an example of using Bluebird promise and promisifying Mongoose using that:
import mongoose from "mongoose";
import Promise from "bluebird";
// promisify mongoose
Promise.promisifyAll(mongoose);
Now, you can use Mongoose as promises and it will not give you the deprecated warning.