Type Error on Transpiling Babel class.default is not a constructor - node.js

'use strict';
/**
* PortalHTML.js
*/
import SingleContextHTML from './SingleContextHTML';
import MultiContextHTML from './MultiContextHTML';
export default class PortalHTML{
constructor (type) {
switch(type) {
case "1":
this.portalStrategy = new SingleContextHTML();
break;
default:
this.portalStrategy = new MultiContextHTML();
break;
}
}
render (...args) {
this.portalStrategy.renderHTML(args);
}
_strategyPeak(){
return this.portalStrategy.constructor.name;
}
}
/**
* SingleContextHTML.js
*/
'use strict';
import PortalHTMLStrategy from './PortalHTMLStrategy';
export default class SingleContextHTML extends PortalHTMLStrategy {
constructor(){
super()
}
renderHTML(args){}
}
/**
* Multi.js (same as single) ^^ above
*/
/**
* PortalHTMLStrategy.js
*/
'use strict';
export default class PortalHTMLStrategy{
constructor(){}
renderHTML(args){}
}
/**
* Tester Mocha and Chai
*/
'use strict';
import PortalHTML from "./PortalHTML";
import chai from 'chai';
let basicPortalHTMLTest = () => {
let singleContextHTML = new PortalHTML("1");
let multiContextHTML = new PortalHTML("multi");
describe('PortalHTML: Initialization of PortalHTML', () => {
it('Should be an instance of class SingleContextHTML', (done) => {
chai.expect(singleContextHTML._strategyPeak()).to.equal('SingleContextHTML');
done();
});
it('Should be an instance of MultiContextHTML', (done) => {
chai.expect(singleContextHTML._strategyPeak()).to.equal('MultiContextHTML');
done();
});
});
};
basicPortalHTMLTest();
I am trying to test an implementation of a strategy pattern, but I am running into an error that states the following after I run my test script with mocha.
var singleContextHTML = new _PortalHTML2.default("1");
^
TypeError: _PortalHTML2.default is not a constructor
I am using node6 and the following babel packages:
"babel-cli": "^6.14.0",
"babel-core": "^6.17.0",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.16.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-2": "^6.11.0"
I have been trying to debug this for around half a day. If anyone sees anything immediately wrong that I am doing I would be extremely grateful.

I was using the incorrect babel preset. Switching over to es2016 or above fixed this error.

Related

Sinon throws on Discordjs ActionRowBuiilder stub

I am struggling with stubbing third party elements with Sinon. Anybody seeing an issue here?
The funny thing is I am running pretty much the exact same test for a different module and it works.
I do admit I am not great on instantiation but really not seeing it.
Code to test
'use strict'
const { ActionRowBuilder, SelectMenuBuilder } = require('discord.js')
class Action {
static async selectHook (interaction, client, deleteId) {
const row = new ActionRowBuilder()
.addComponents(
new SelectMenuBuilder()
.setCustomId('confirmselect')
.setPlaceholder('Please confirm')
.addOptions(
{
label: 'I confirm',
description: `Confirm hook #${deleteId}`,
value: deleteId
}
)
)
await interaction.update({
content: 'Hook was selected! Please confirm ' +
'by using the select menu again.',
components: [row],
ephemeral: true
})
}
}
Test file
'use strict'
const sinon = require('sinon')
const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
const sinonChai = require('sinon-chai')
chai.use(chaiAsPromised)
chai.use(sinonChai)
const expect = chai.expect
const { ActionRowBuilder, SelectMenuBuilder } = require('discord.js')
const client = {
once () {},
on () {},
},
const interaction = {
reply () {},
followUp () {},
update () {},
},
describe('app/Action', function () {
afterEach( function () {
sinon.restore()
})
describe('Action.selectHook', function () {
it(' should run interaction.update', async function () {
const updateStub = sinon.stub(interaction, 'update')
.resolves()
sinon.spy(function () {
return sinon.createStubInstance(ActionRowBuilder)
})
sinon.spy(function () {
return sinon.createStubInstance(SelectMenuBuilder)
})
await Action.selectHook(interaction, client, 1)
sinon.assert.calledOnceWithMatch(
updateStub,
{
content: 'Hook was selected! Please confirm ' +
'by using the select menu again.'
}
)
})
})
})
I have also tried with
sinon.createStubInstance(SelectMenuBuilder)
sinon.createStubInstance(ActionRowBuilder)
Anyways I get
1) should run interaction.update
0 passing (199ms)
1 failing
1) app/Action
Action.selectHook
should run interaction.update:
Error: Received one or more errors
at UnionValidator.handle (node_modules/#sapphire/shapeshift/dist/index.js:1085:23)
at UnionValidator.parse (node_modules/#sapphire/shapeshift/dist/index.js:142:88)
at /home/axel/Dropbox/0_Programming/discordjs-captain-hook/node_modules/#discordjs/builders/dist/index.js:557:147
at Array.map (<anonymous>)
at SelectMenuBuilder.addOptions (node_modules/#discordjs/builders/dist/index.js:557:34)
at SelectMenuBuilder.addOptions (node_modules/discord.js/src/structures/SelectMenuBuilder.js:48:18)
at Function.selectHook (app/Action.js:108:22)
at Context.<anonymous> (tests/mocha/Action.js:265:26)
at processImmediate (node:internal/timers:464:21)
Running on
Nodejs: v16.13.2
"discord-api-types": "^0.37.2",
"discord.js": "^14.2.0",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"mocha": "^10.0.0",
"nyc": "^15.1.0",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0"

How To Mock a Dependency Class in Typescript Node Using Chai-Spies

Given something like my-module.ts that will be called by an external consumer that of course cannot do dependency injection to this module's constructor:
import Dependency from 'dependency-class';
import {myDataFormat} from '../types/my-module-types';
export default class MyModule {
private dependency: Dependency;
constructor() {
this.dependency = new Dependency();
}
getMyData(): myDataFormat {
const dependencyData = this.dependency.getDependencyData();
// parse/process data
// return modified data
}
}
How can we test that Dependency.getDependencyData() was called by MyModule.getMyData()... using only mocha, chai, and chai-spies?
my-module.test.ts:
import Dependency from 'dependency';
import MyModule from '../src/modules/my-module'
import 'mocha';
import chai = require('chai');
chai.should(); //enable chai should()
import spies = require('chai-spies');
chai.use(spies); //extend chai with spies plugin
describe('Tests.MyModule', () => {
let instance: MyModule | undefined;
before(() => {
// Create spies/stubs/mocks as needed
chai.spy.on(Dependency.prototype, ['getDependencyData'], () => {
// this is replacement function body if we want to test specific return data
});
// Create MyModule instance
instance = new MyModule();
});
after(() => {
// Reset MyModule instance
instance = undefined;
// Remove spies/stubs/mocks that were created
chai.spy.restore();
});
describe('getMyData()', () => {
it('should call Dependency.getDependencyData()', () => {
// Arrange
// - Set up spies/stubs/mocks (done above)
// - Create a MyModule instance (done above)
// Act
instance.getMyData();
// Assert
Dependency.prototype.getDependencyData.should.have.been.called();
});
});
});
Versions in Node package.json:
"#types/chai": "^4.3.0",
"#types/chai-spies": "^1.0.3",
"#types/mocha": "^9.1.0",
"chai": "^4.3.6",
"chai-spies": "^1.0.0",
"mocha": "^9.2.1",

nodejs unit test PubSub.publish not sending data

I'm having issues doing a unit test with the following environment:
"pubsub-js": "^1.9.2",
"#types/chai": "^4.2.14",
"#types/mocha": "^8.2.0",
"chai": "^4.2.0",
"firebase-functions-test": "^0.2.3",
"mocha": "^8.2.1",
"ts-node": "^9.1.1",
"ts-sinon": "^2.0.1",
When publish a message to my pubsub the data received by it is always: Message { data: undefined, attributes: {}, _json: undefined } and I can't figure out why.
There is some code to describe my scenario:
pubsub-myFunc.ts
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1")
console.log(message)
/**
* Received message from topic
*/
const myMessage = Buffer.from(message.data, "base64").toString("utf-8")
pubsub-myFunc.spec.ts
import * as functions from 'firebase-functions';
import * as PubSub from 'pubsub-js';
import * as tsSinon from 'ts-sinon';
import { pubsubMyFunc } from './pubsub-myFuncr';
import * as sendEmail from './send-mail';
describe("PubSub tests", () => {
beforeEach(() => {
process.env.GCLOUD_PROJECT = "my env"
})
it("Should call sendNotificationMessage", function (done) {
// this.timeout(60000)
const today = new Date()
const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
}
const spy = tsSinon.default.spy(sendEmail, "sendNotificationMessage")
const dataBuffer = Buffer.from(JSON.stringify(data))
const pubsubMessage = new functions.pubsub.Message(dataBuffer)
PubSub.subscribe("on-myTopic", pubsubMyFunc)
console.log("publish")
PubSub.publish("on-myTopic", pubsubMessage)
setTimeout(() => {
// check if spy was called
tsSinon.default.assert.calledOnce(spy)
done()
}, 15000)
})
})
I have tried to pass directly the dataBuffer but without any luck as well, the outputs of my console logs are:
publish
version 1
Message { data: undefined, attributes: {}, _json: undefined }
Is there any reason for my Message.data to be undefined?
I'm not sure if pubsub-js's subscribe function is compatible with the output of firebase-functions' onPublish method.
You could use firebase's emulators to run your functions locally and test them by sending messages like you would normally instead of going through pubsub-js.
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");
console.log(message);
/**
* Received message from topic
*/
const myMessage = message.json;
...
Make sure pubsubMyFunc is being exported at firebase functions entry point.
Install and configure firebase emulators, make sure PUBSUB_EMULATOR_HOST env var is set to localhost:$PORT where $PORT is set to the port you have configured for pub sub emulator, located in firebase.json under emulators.pubsub.port.
Once that's all setup, you can send a message to pubsub by:
import {PubSub} from "#google-cloud/pubsub";
cont getTopic = () => {
const topic = new PubSub().topic("on-myTopic");
topic.exists().then(([exists]) => exists
? topic
: topic.create().then(([newTopic]) => newTopic)
);
};
describe("PubSub tests", () => {
let topic;
beforeEach(async() => {
process.env.GCLOUD_PROJECT = "my env"
topic = await getTopic();
});
it("should test something", async() => {
await topic.publishJSON(const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
});
// rest of your code here.
});
});
This will work on the process of hack
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");

ESM import not working with redux, Node 10.1.0

//index.mjs
import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp)
import {
addTodo,
toggleTodo,
setVisibilityFilter,
VisibilityFilters
} from './actions'
// Log the initial state
console.log(store.getState())
// Every time the state changes, log it
// Note that subscribe() returns a function for unregistering the listener
const unsubscribe = store.subscribe(() =>
console.log(store.getState())
)
// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))
store.dispatch(addTodo('Learn about reducers'))
store.dispatch(addTodo('Learn about store'))
store.dispatch(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))
// Stop listening to state updates
unsubscribe()
//reducers.mjs
import { combineReducers } from 'redux'
import {
ADD_TODO,
TOGGLE_TODO,
SET_VISIBILITY_FILTER,
VisibilityFilters
} from './actions'
const { SHOW_ALL } = VisibilityFilter
function visibilityFilter(state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
function todos(state = [], action) {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
text: action.text,
completed: false
}
]
case TOGGLE_TODO:
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
default:
return state
}
}
const todoApp = combineReducers({
visibilityFilter,
todos
})
export default todoApp
// actions.mjs
/*
* action types
*/
export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
/*
* other constants
*/
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
/*
* action creators
*/
export function addTodo(text) {
return { type: ADD_TODO, text }
}
export function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
export function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter }
}
Edit- added code
I am working through the Redux Basics tutorial from the Redux docs, and am having trouble getting import to work properly.
I currently have 3 files for my todo-list app:
actions.mjs
reducers.mjs
index.mjs
I have done an npm init -y, and npm install --save redux. I copy and pasted the source code directly from the Redux docs for all 3 files.
With the command: node --experimental-modules index, I get the error:
SyntaxError: The requested module 'redux' does not provide an export named 'combineReducers'
I would expect similar error messages for other named exports of Redux...
I have had success with refactoring back to CommonJS using require, module.exports, .js file extensions, and the command: node index.js

Jest Testing with require modules: ejs-loader

I am playing with the idea of having large static html bundles just loaded into a react component vice typing them all out in jsx. I am currently just experimenting with ejs-loader and html-react-parser to evaluate the feasibility of this. Everything actually renders fine but I cannot get any tests to work with jest for this.
I receive: Cannot find module ejs-loader!./AboutPage.view.ejs from AboutPage.js errors and I am unsure of what to do.
I am currently just working off of react-slingshot as my base for experimenting with this.
The repo for the project is here
The component itself is simple:
import React from 'react';
import Parser from 'html-react-parser';
import '../styles/about-page.css';
const view = require('ejs-loader!./AboutPage.view.ejs')();
// Since this component is simple and static, there's no parent container for it.
const AboutPage = () => {
return (
<div>
{Parser(view)}
</div>
);
};
export default AboutPage;
And the test is:
import React from 'react';
import {shallow} from 'enzyme';
import AboutPage from './AboutPage';
describe('<AboutPage />', () => {
it('should have a header called \'About\'', () => {
const wrapper = shallow(<AboutPage />);
const actual = component.find('h2').text();
const expected = 'About';
expect(actual).toEqual(expected);
});
});
I have read through the docs and similar questions like this. I attempted to use a custom transformer, but I may be misunderstanding something as it doesn't appear to be even called.
Package.json
"jest": {
"moduleNameMapper": {
"\\.(css|scss)$": "identity-obj-proxy",
"^.+\\.(gif|ttf|eot|svg|woff|woff2|ico)$": "<rootDir>/tools/fileMock.js"
},
"transform": {
"^.+\\.js$": "babel-jest",
"\\.(ejs|ejx)$": "<rootDir>/tools/ejx-loader/jest.transformer.js"
}
},
and the transformer itself:
module.exports = {
process(src, filename, config, options){
console.log('????');
return 'module.exports = ' + require(`ejs-loader!./${filename}`);
//return require(`ejs-loader!./${filename}`);
}
};
Can you try changing module name mapper to -
{
"\\.(css|scss)$": "identity-obj-proxy",
"^.+\\.(gif|ttf|eot|svg|woff|woff2|ico)$": "<rootDir>/tools/fileMock.js"
"ejs-loader!(.*)": "$1",
}
This should at least invoke your custom transformer.
Also the custom transformer should be -
const _ = require('lodash');
module.exports = {
process(src, filename, config, options){
console.log('????');
return 'module.exports = ' + _.template(src);
}
};
It doesn't look like you've specified .ejs as a moduleFileExtension.
"jest": {
...
"moduleFileExtensions": ["js", "jsx", "ejs", "ejx"],
...
}
Also, ejs-loader will export the function using cjs syntax for you, so you can do the following in your transformer:
const loader = require('ejs-loader');
module.exports = {process: loader};
Work for me:
"jest": {
"moduleNameMapper": {
'\\.(ejs|ejx)$': '<rootDir>/jest-ejs.transformer.js'
},
moduleFileExtensions: ['js', 'json', 'jsx', 'ejs']
},
In jest-ejs.transformer.js
const loader = require('ejs-loader');
module.exports = {process: loader};

Resources