Firebase Function import function from other file - javascript - javascript

I am building firebase function with javascript. Now i have a lot of inter-call function and i plan to move those function into different file to avoid index.js become very messy.
So below is the current file structure:
/functions
|--index.js
|--internalFunctions.js
|--package.json
|--package-lock.json
|--.eslintrc.json
I want to know:
1) How to export the function from internalFunctions.js and import it to index.js.
2) How to call internalFunctions.js function from index.js.
My code is written in JavaScript.
Edited
internalFunction.js will have multiple functions.

First you set the function in your file:
internalFunctions.js:
module.exports = {
HelloWorld: function test(event) {
console.log('hello world!');
}
};
Or if you dont like a lot messing with curly braces:
module.exports.HelloWorld = function(event) {
console.log('hello world!');
}
module.exports.AnotherFunction = function(event) {
console.log('hello from another!');
}
There are also other styles you can use: https://gist.github.com/kimmobrunfeldt/10848413
Then in your index.js file import the file as a module:
const ifunctions = require('./internalFunctions');
And then you can call it directly within your triggers or HTTP handlers:
ifunctions.HelloWorld();
Example:
//Code to load modules
//...
const ifunctions = require('./internalFunctions');
exports.myTrigger = functions.database.ref('/myNode/{id}')
.onWrite((change, context) => {
//Some of your code...
ifunctions.HelloWorld();
//A bit more of code...
});

Related

jest.mock not working with Javascript test and Typescript module

My mocked utilFunction isn't being used and adding logging to the factory function shows that it's never called. I've already tried searching for jest.mock not working with relative paths and jest.mock not being called for Typescript thinking that it might be related to the mix of JS tests and TS source code or to the different module paths used in the source vs test code.
Code being tested:
// src/foo/fooModule.ts
import { utilFunction } from '../util'
export const foo = () => {
return utilFunction()
}
Test code:
// test/fooModule.test.js
const { foo } = require('../src/foo/fooModule')
jest.mock('../src/util', () => {
return { utilFunction: () => 'mocked' };
});
describe('fooModule tests', () => ...)
The jest.mock call needs to be moved above the imports:
// test/fooModule.test.js
jest.mock('../src/util', () => {
return { utilFunction: () => 'mocked' };
});
const { foo } = require('../src/foo/fooModule')
describe('fooModule tests', () => ...)
My last experience working with Jest prior to this was in a project where the tests were also written in Typescript and babel-jest was used. babel-jest includes babel-jest-hoist which hoists the jest mocks above any imports automatically, so I didn't previously have to worry about the ordering.

Testing web components with jsdom

I have a web component I've built which is bundled (using Rollup) into a UMD and ESM package. The src/index.js basically looks like this.
import html from 'template.html';
import css from 'styles.css';
export class MyComponent extends window.HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
}
export default (function() {
window.customElements.define('my-component', MyComponent);
})()
I'm well aware about how weird this looks, and I'm open to suggestions on cleaning this up so testing actually works.
I'm trying to test my web component using mocha and jsdom-global. The problem is I can't get the component to mount. In other words, this fails:
import jsdomGlobal from 'jsdom-global';
import { expect } from 'chai';
import { MyComponent } from '../dist/my-component.esm';
describe('test', function() {
let jsdom;
before(function(){
jsdom = jsdomGlobal('', { runScripts: 'dangerously' });
const script = document.createElement('script');
script.textContent = `window.customElements.define('my-component', (${MyComponent}))`;
document.head.appendChild(script);
})
after(function() {
jsdom();
});
it('mounts', async function() {
await window.customElements.whenDefined('my-component');
expect(window.customElements.get('my-component')).to.exist;
})
})
I've also tried not wrapping in a new window.customElements.define call because I assumed the IIFE would just execute once the file is referenced but that doesn't seem to be the case?
As an aside, if anyone knows how to test the /src files directly instead of the /dist, that would be awesome. I assume there's some way that mocha and rollup could work together to do a better job in identifying coverage. As it stands right now, coverage just shows a single line of failures not anything against the lines in the source.
Ok, I have some success after trying all sorts of things.
import { JSDOM } from 'jsdom';
import { expect } from 'chai';
import fs from 'fs';
import { resolve } from 'path';
import { promisify } from 'util';
const readFile = promisify(fs.readFile);
async function getHTML() {
const script = await readFile(resolve(__dirname, '..', 'dist', 'my-component.umd.js'));
return `<html><head><script>${script}</script></head><body></body></html>`;
}
describe('my-component', function () {
describe('browser context', function() {
let window, document;
before(async function() {
const html = await getHTML();
const dom = new JSDOM(html, { runScripts: 'dangerously', resources: 'usable' });
window = dom.window;
document = window.document;
});
it('defines a custom element', async function() {
await window.customElements.whenDefined('my-component');
expect(window.customElements.get('my-component')).to.exist;
})
})
})
So this passes the assertion but because the test has no idea about the script, there's no coverage metrics.
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 0 | 0 | 0 | 0 |
----------|---------|----------|---------|---------|-------------------
It would be nice to be able to test and report coverage, but this'll have to do for now.

Importing custom CommonJS module fails

I created a CommonJS module in project A in the following way:
const { WebElement } = require('selenium-webdriver');
const { By } = require('selenium-webdriver');
class VlElement extends WebElement {
constructor(driver, selector) {
...
}
async getClassList() {
...
}
}
module.exports = VlElement;
In project B I use the following code:
const VlElement = require('projectA');
class VlButton extends VlElement {
constructor(driver, selector) {
super(driver, selector);
}
...
}
module.exports = VlButton;
When running the code, VLElemlent cannot be found.
It is in my package.json and I can see VLElement under projectB > node_modules > projectA.
What am I doing wrong with my exports?
Thanks in advance.
Regards
Make sure you have a projectB/mode_modules/package.json with a main which points to the file that defines/exports VlElement, like this:
"main": "path/to/file/with/VlElement.js",
When you call require('projectA'); this has to be resolved to a file inside projectA so that it can be evaluated to (and return) the exports from that file. The main entry in the package.json allows this (but defaults to index.js, so if you are using that you don't need package.json, probably, but you should have it anyway).
You can have multiple files with various exports, but remember require('projectA'); can still only return one thing, so the way to do that is usually to have an index.js which looks something like:
module.exports = {
'something': require('./something.js'),
'otherthing': require('./otherthing.js'),
'etc': require('./etc.js'),
};

Nodejs imported module is undefined, but works when checked with if statement or when order of import is changed

I am running into a strange issue.
xxx.testFunction(); statement when executed errors out: TypeError: Cannot read property 'testFunction' of undefined, but works when executed with pre-condition if(xxx)..
Issue can be recreated in the following setup
index.js
const { Module1 } = require("./Module1"); //Commenting out this line fixes the issue
const { Module3 } = require("./Module3");
Module3.testFunction();
Module1.js
const { Module2 } = require("./Module2");
class Module1 {
static testFunction() {
console.log("testFunction")
}
}
module.exports = { Module1 };
Module2.js
const { Module3 } = require("./Module3"); //Commenting out this line also fixes the issue
class Module2 {
}
module.exports = { Module2 };
Module3.js
const { Module1 } = require("./Module1");
class Module3 {
static testFunction() {
//if(Module1) //If we merely check this first it works, but directly it doesn't
Module1.testFunction();
}
}
module.exports = { Module3 };
Moreover, if some of the require statements are removed, the function gets executed..
It also gets fixed when order of requires in index.js is changed.
If you're wondering why the extra requires, the reason is that they were needed for other code in the modules.. The above code is a stripped down version of the production code we found the issue in.
As per my understanding variables in nodejs modules are scoped to the module, and should not have any effect on other modules..
Can someone explain this behavior..
It seems that you have a circular dependency. to solve it you can require in the function itself as if you make Module3.js looks like:
class Module3 {
static testFunction() {
const { Module1 } = require("./Module1");
Module1.testFunction();
}
}
module.exports = { Module3 };

JavaScript ES6 Module OnLoad handler implementation

I have a NodeJS server application which is split to lost of ES6 modules. I am trying to create a kind of "load module handler", a function in the main module, which other modules would require to register a callback, which will be executed after the main module is fully initialized. I am using Babel (with babel-preset-es2015) to transpile ES6 modules into executable JavaScript.
To demonstrate the issue here in short, I've created 2 sample files.
File index.js (application entry, main module):
import * as js2 from "./js2.js";
let toCall = [], // this array handles callbacks from other modules
initialized = false; // flag
export function onInit (cb) { // registers cb to execute after this module is initialized
if (initialized) {
cb();
return;
}
toCall.push(cb);
}
function done () { // initialization is done - execute all registered callbacks
toCall.forEach(f => f());
}
// some important stuff here
// callback(() => {
initialized = true;
done();
// });
And the other module js2.js:
import { onInit } from "./index";
onInit(() => {
console.log("Now I can use initialized application!");
});
All seems to be OK to me, but unfortunately this doesn't work throwing the next error in the first file:
Cannot read property 'push' of undefined
Thing is, there is no toCall variable at this point, but why? Variable toCall is declared before onInit function, it must be ready to use in onInit, mustn't it? How to solve this and is my way rational enough to implement something called "module initialization callbacks"? Are there any other solutions for this?
Thank you for any help and advice.
I found a beautiful implementation for this.
It is needed to separate "onload handler" implementation to individual module. As a result of this example, there will be three files:
index.js:
import * as js2 from "./js2.js";
import { initDone } from "./init.js";
// some important stuff here
// callback(() => {
console.log(`Main module is initialized!`);
initDone();
// });
js2.js:
import { onInit } from "./init.js";
onInit(() => {
console.log("Module js2.js is initialized!");
});
init.js:
let toCall = [], // this array has to handle functions from other modules
initialized = false; // init flag
export function onInit (cb) {
if (initialized) {
cb();
return;
}
toCall.push(cb);
}
export function initDone () {
initialized = true;
toCall.forEach(f => f());
}
And the result:
Main module is initialized!
Module js2.js is initialized!

Categories