how to export javascript function as a module - javascript

I've exported a function and imported it in Javascript, but the only way i can access the functions inside it is by typing it like this:
myModule.mainFunc().func1()
But what i'm trying to achieve is more like this:
myModule.mainFunc.func1()
Currently it gives an error if i try to reference to it like this.
I've tried returning the values of the functions as objects but it still needs me to call it as functions.
function greet() {
var hello = () => {
console.log("hello there");
};
var hi = () => {
console.log("hi there");
};
return { hello: hello, hi: hi }; // I've tried this doing it like this
}
export default {greet};
Here's how I'm importing it:
import greetings from "./index.js";
greetings.greet().hello()

define greet as an object
var greet = {
hello: () => {
console.log("hello there");
},
hi: () => {
console.log("hi there");
},
}
and access it like greet.hello()

You can't reference the functions defined inside greet function as
myModule.mainFunc.func1()
because myModule.mainFunc is a greet function itself. What you want to import is the result of calling greet function.
You can avoid invoking the greet function manually by making your function an IIFE (Immediately Invoked Function Expression). Doing this will execute the function as soon as it is defined.
const greet = (function() {
var hello = () => {
console.log("hello there");
};
var hi = () => {
console.log("hi there");
};
return { hello, hi };
})();
export default { greet };
Now when you export greet, you are not exporting greet function, but the result of calling greet function which is an object with two functions, hello and hi.

Which environment you're running your code ? If it's NodeJS, make sure it supports ES6 Module as your current style of export and import. Normal NodeJS just supports CommonJS module.

Related

How to spyOn an exported standalone function using javascript jest?

It is a very simple scenario but I've struggled to find an answer for it.
helpers.ts:
export function foo() {
bar();
}
export function bar() {
// do something
}
helpers.spec.ts:
import { foo, bar } from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = // how can i set this up?
foo();
expect(barSpy).toHaveBeenCalled();
});
});
I can't do const spy = jest.spyOn(baz, 'bar'); because I don't have a module/class to put in place of "baz". It is just an exported function.
Edit:
Jest mock inner function has been suggested as a duplicate but unfortunately it doesn't help with my scenario.
Solutions in that question:
Move to separate module: I cannot do this for my scenario. If I am testing every function in my application, this would result in me creating 10s of new files which is not ideal. (To clarify, I think this solution would work but I cannot use it for my scenario. I am already mocking a separate file function successfully in this test file.)
Import the module into itself:
helpers.spec.ts:
import * as helpers from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = jest.spyOn(helpers, 'bar');
foo();
expect(barSpy).toHaveBeenCalled();
});
});
results in:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
This is the closed solution:
export function bar() {
// do something
}
export function foo() {
exports.bar(); // <-- have to change to exports.bar() instead of bar()
// or this.bar(); would also work.
}
import * as utils from './utils';
describe('tests', () => {
it('example test', () => {
const barSpy = jest.spyOn(utils, 'bar');
utils.foo();
expect(barSpy).toHaveBeenCalled();
});
});
Or take a look this duplicated question

How to test functions in a function using Jest

I have some code that has functions inside functions, and I want to be able to unit test the functions inside the parent function.
I am looking to have tests that unit test these and spy on them (both requirements are needed).
Example:
export default parentFunction = () => {
const innerFunction = () => {
//that does stuff
}
const anotherInnerFunction = () => {
//that does more stuff
}
//and at some point, the functions are called
//like this
innerFunction()
const anotherFunction = () => {
//or like this
anotherInnerFunction()
}
}
I have not been able to find a way to test these inner functions. I have tried the following.
Example test
import parentFunction from "myfile"
it("should call innerFunction", () => {
//this causes an error in jest
const innerFunctionSpy = jest.spyOn(parentFunction, "innerFunction")
//..etc
expect(innerFunctionSpy).toHaveBeenCalled()
})
it("will return a value from anotherInnerFunction", () => {
//this does not work
const value = parentFunction.anotherInnerFunction()
//this also does not work
const value = parentFunction().anotherInnerFunction()
//..etc
})
Does the parent function need to be refactored in order to be able to tests these inner functions? If my parent function was an object then I could test these, however, I am not sure if I can refactor my code to work like this.
For example
export default parentFunction = {
innerFunction: () => {
//that does stuff
},
//more code
}
You cannot access the variables or functions scoped inside another function in JavaScript. Unless you explicitly expose them by returning them from that function or export them from the module. This is not about Jest, this is how it works in JavaScript.
jest.spyOn(parentFunction, "innerFunction")
The above line of code indicates to Jest that the innerFunction function is set as a property of the parentFunction object but that is not the case. In fact innerFunction is a function scoped inside the parentFunction which cannot be accessed from outside of the scope of parentFunction. Unless you return it explicitly or define it on the module level scope and then export it.
But the inner workings or the implementation details of such inner functions should not be exposed, but if it is needed it should be marked as such using an _ before its name, take the following example:
//scoped to the module
const _innerFunction = () => {
//that does stuff
}
//scoped to the module
const _anotherInnerFunction = () => {
//that does more stuff
}
//exported as a public API
const anotherFunction = () => {
_anotherInnerFunction()
}
const publicApi = {
anotherFunction,
// expose the private functions for unit tests
_innerFunction,
_anotherInnerFunction
}
export default publicApi;
Then in your Jest test case:
import publicApi from "myfile"
it("should call anotherFunction", () => {
const anotherFunctionSpy = jest.spyOn(publicApi, "anotherFunction")
//..etc
expect(anotherFunctionSpy ).toHaveBeenCalled()
})
it("should call _innerFunction", () => {
const innerFunctionSpy = jest.spyOn(publicApi, "_innerFunction")
//..etc
expect(innerFunctionSpy ).toHaveBeenCalled()
})

Using a function defined inside an exports function, from another file

I have some code like this in a file helperFunctions.js:
exports helperFunctions = () => {
const functionA = async(args) => {
console.log(args);
};
const functionB = async(args) => {
functionA(myArg);
};
}
How can I call functionA and functionB from a separate file altogether, say, main.js?
I've tried:
import { helperFunctions } from './helperFunctions';
//...some code
helperFunctions.functionA('hello');
// OR
functionA('hello');
The specific error is:
TypeError: _helperFunctions.helperFunctions.functionA is not a function
and when trying the second solution, it's:
ReferenceError: functionA is not defined
I'm trying to avoid importing literally every single function I'm using (by way of exporting every single function I'm using). I'd like to do something like helperFunctions.function for the functions I need.
It really need to be a function? You could export an Object:
// helperFunctions.js
let helperFunctions = {
functionA: async (args) => {
console.log(args);
},
functionB: async (args) => {
functionA(myArg);
}
}
exports helperFunctions;

Jest having trouble mocking specific function

I've started using jest but I've been having some trouble mocking specific JS functions, I've already tried various would be solutions to this but i just couldn't get it to work.
Below is my JavaScript function code
functions.js :
function test1(){
return "hello1"
}
function test2(){
return "hello2"
}
module.exports = test1;
module.exports = test2;
and this is my jest code:
function.test.js
const testfunction = require('/function');
test('tooltip Correct DOM element test', () => {
expect(testfunction.test1).toBe("hello1");
});
You are exporting the function incorrectly. You need to do:
function test1() {
return "hello1"
}
function test2() {
return "hello2"
}
module.exports = {
test1: test1,
test2: test2
};
Exporting the function in this way will enable to get testfunction.test1 inside the test file. And you need to call the function inside the test script like:
expect(testfunction.test1()).toBe("hello1");

ES6 access exported 'default' instance from same file

I was wondering, when you export some data using the ES6 keyword export like so :
export default {
data: "Hello !"
}
How can you then from the same file, access that exact same exported data ?
EDIT: Of course, without declaring it before exporting the variable...
If you structure your file like that, you cannot.
Usually, you define functions and data that you want to expose before the export statement, and then reference them when you build the exported object/function.
Bad way:
export default {
data: 'Hello!',
myFn: function (str) {
console.log(str);
}
}
Good way:
var data = 'Hello!';
var myFn = function (str) {
console.log(str);
};
// code that uses data and myFn
// shorthand for { data: data, myFn: myFn }
export default { data, myFn };
Try the following
export const data = 'hello';
For my similar use case -- I wanted easy access to everything the ES6 module exported from within the same module just for debugging purposes. So:
export const data = 'hi'
export const someFunc = () => `important data: ${data}`
export default someFunc()
export const funcToDebug() => {
console.log(`what's going on here? ${myModule.exports.default}`)
}
var myModule = module
If you want to access internally the functions that you export, you should define them outside of the export statement. Like so:
const data = 'Hello !';
const someFunc = () => {
return data + ' Goodbye!'
}
export default {
data,
someFunc
}
Now the variables and functions can reference each other without being "stuck" inside the export function. For example the following will NOT work:
// WRONG!
export default {
data: 'Hello !',
someFunc: () => {
return data + ' Goodbye!';
}
}

Categories

Resources