I'm using express-prom-bundle to provide a prometheus statistics endpoint, this library creates a middleware that is applied to an Express app:
import promBundle from 'express-prom-bundle';
...
app.use(promBundle({
includeMethod: process.env.PROMETHEUS_INCLUDE_METHOD === 'true' ? true : false,
includePath: process.env.PROMETHEUS_INCLUDE_PATH === 'true' ? true : false,
includeStatusCode: process.env.PROMETHEUS_INCLUDE_STATUS_CODE === 'true' ? true : false,
}));
This is what I'm currently trying to do:
import * as promBundle from 'express-prom-bundle';
...
spyOn(promBundle, 'default');
spyOnProperty(promBundle, 'default').and.returnValue({});
expect(promBundle).toHaveBeenCalled();
but I'm receiving the following error:
Error: <spyOn> : default is not declared writable or has no setter Usage: spyOn(<object>, <methodName>)
How it could be mocked and tested by Jasmine?
Coverage shows that lines where process.env variables are checking need to be tested.
Related
I am building a nestJs application, with scheduling and configuration. I want to be able to configure my Cron with my environment variable but it does not seems to work.
app.module.ts :
#Module({
imports: [
ConfigModule.forRoot(),
ScheduleModule.forRoot(),
SchedulingModule,
...
],
})
export class AppModule {}
scheduling.service.ts (from my SchedulingModule) :
#Cron(process.env.CRON_VALUE)
scheduledJob() {
this.logger.log('Scheduled : Job');
...
}
.env :
...
CRON_VALUE=0 4 * * *
...
Apparently at the moment the value is checked it's empty. I got the following error :
(node:55016) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '_isAMomentObject' of undefined
at new CronTime (/Users/antoinegrenard/Documents/Projet/b4finance/service-scheduling/node_modules/cron/lib/cron.js:42:50)
at new CronJob (/Users/antoinegrenard/Documents/Projet/b4finance/service-scheduling/node_modules/cron/lib/cron.js:527:19)
at /Users/antoinegrenard/Documents/Projet/b4finance/service-scheduling/node_modules/#nestjs/schedule/dist/scheduler.orchestrator.js:56:29
...
Apparently it is not possible to get env values in decorators.
I had to do it this way :
constructor(private schedulerRegistry: SchedulerRegistry) {}
onModuleInit() {
const job = new CronJob(process.env. CRON_VALUE, () => {
// What you want to do here
});
this.schedulerRegistry.addCronJob(name, job);
job.start();
}
To fix this problem you should load the config on your service again:
require('dotenv').config();
I try to load a translation JSON file from API in React Native and parse it but it seems that load does not work because the parse method never invokes.
function initI18Next(onInit) {
return (
i18n
.use(initReactI18next)
.use(XHR)
.init({
...initOptions,
backend : backendOptions
}).then(onInit())
)}
initOptions :
export const initOptions = {
fallbackLng : 'es',
defaultNS : 'translation',
lng : 'es',
debug: true,
keySeparator : false,
initImmediate: false,
preload : ['en', 'es'],
react: {
wait: true,
useSuspense: false
},
interpolation: {
escapeValue: true // not needed for react as it escapes by default
},
resources : i18nResources
}
backend options :
export const backendOptions = {
loadPath: 'http://www.mocky.io/v2/5ecd0fe73200006400236655.json',
parse(data) {
console.log('data', data);
return data;
}
};
i18next-xhr-backend is deprecated, use i18next-http-backend instead...
Then try to set i18next debug option to true and have a look at the developer console logs.
Btw: the load path looks strange to me. It should be more like this: https://github.com/i18next/i18next-http-backend#backend-options
The documentation at i18next-xhr-backend tells me to use import to load their module. But when I use the import-statement, nothing happens and Firefox gives me a SyntaxError in the developer console:
SyntaxError: import declarations may only appear at top level of a module
So how can I use i18next library with the XHR-backend? The following code example works if the .use(XHR)-line and the corresponding import is commented out (Warning: i18next::backendConnector: No backend was added via i18next.use. Will not load resources.). But it fails, if it is not: ReferenceError: XHR is not defined
//import Fetch from 'i18next-fetch-backend';
let t = null;
i18next
.use(XHR)
.init({
debug: true,
fallbackLng: ['en'],
preload: ['en'],
ns: 'translation',
defaultNS: 'translation',
keySeparator: false, // Allow usage of dots in keys
nsSeparator: false,
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
}, (err, _t) => {
if (err) {
reject(err);
return;
}
t = _t;
//resolve();
});
jqueryI18next.init(i18next, $, {
tName: 't', // --> appends $.t = i18next.t
i18nName: 'i18n', // --> appends $.i18n = i18next
handleName: 'localize', // --> appends $(selector).localize(opts);
selectorAttr: 'data-i18n', // selector for translating elements
targetAttr: 'i18n-target', // data-() attribute to grab target element to translate (if different than itself)
optionsAttr: 'i18n-options', // data-() attribute that contains options, will load/set if useOptionsAttr = true
useOptionsAttr: false, // see optionsAttr
parseDefaultValueFromContent: true // parses default values from content ele.val or ele.text
});
$(".nav").localize();
I needed to use i18nextXHRBackend instead of just XHR, since that is the name the class gets loaded as if no loader is used. As the README.md says:
If you don't use a module loader it will be added to window.i18nextXHRBackend
I didn't see that before, and I didn't know that this will happen automatically, but it seems that you have to find that out on your own if not using a module loader. Lesson learned, hopefully this will help some other newbies being stuck on how to use modules in javascript. Therefore, my complete localisation.js looks like this:
$(document).ready(function() {
i18next
.use(i18nextXHRBackend)
.use(i18nextBrowserLanguageDetector)
.init({
debug: true,
backend: {
loadPath: 'locales/{{lng}}/{{ns}}.json',
addPath: 'locales/add/{{lng}}/{{ns}}'
}
}, function(err, t) {
jqueryI18next.init(i18next, $);
$('.translatable').localize();
$('.language-button').click(function() {
i18next.changeLanguage(this.firstElementChild.alt).then(function(t) {
$('.translatable').localize();
$('#signupPassword').pwstrength("forceUpdate");
$('#signupPasswordConfirm').pwstrength("forceUpdate");
});
});
});
});
Iam using Alt.js with React and getting error in HomeActions.js file HomeActions.js: Uncaught TypeError: Cannot read property 'updateUserSuccess' of undefined. Not to mention the same code was working flawlessly before i completely reinstalled node_modules.
here is the code
import alt from '../../alt';
import request from 'superagent';
class HomeActions {
constructor() {
this.generateActions(
'updateUserSuccess',
);
}
getUser() {
request
.get('api/getuser')
.end((err, res) => {
this.actions.updateUserSuccess(res.text);
});
}
}
export default alt.createActions(HomeActions);
getUser() is called in the componenetdidmount(){} function of Home.js
Also directly calling the action property from the component does work so i guess the problem is not with Alt.js or generateActions : eg
import alt from '../../alt';
class NavbarActions {
constructor() {
this.generateActions(
'updateOnlineUsers'
);
}
}
export default alt.createActions(NavbarActions);
//in Navbar.js
componentDidMount() {
NavbarStore.listen(this.onChange);
NavbarActions.updateOnlineUsers(somedata);
}
//this is working**
This question might be related to my last question about calling a function inside an instance method.
Sidenote : After updating the dependencies I also had to make changes to use RouterContext istead of RoutingContext in the server-side react-middle-ware, and to solve an issue related to that I imported browserHistory from react-router (before i was using createBroswerHistory from 'history/createBrowserHistory')
Edit 1 : I replaced this.actions.updateUserSuccess(res.text); with alt.actions.HomeActions.updateUserSuccess(res.text); and the updateUserSuccess is accessible but still getting a warning ReferenceError: An action was called but nothing was dispatched
Edit 2 : I just got to the core of the issue by using console.log(this); in the newer version and also in the older version here are the logs
Older version :
AltAction {id: "HomeActions.getTwoCharacters", actions: Object, actionDetails: Object, alt: Alt, dispatched: false}
_dispatch : ()
actionDetails :
Object actions :
Object alt :
Alt dispatched :
false id :
"HomeActions.getTwoCharacters"
__proto__ : Object
New Version
Object {GET_USER: "HomeActions.getUser", LOGOUT: "HomeActions.logout", UPDATE_USER_SUCCESS: "HomeActions.updateUserSuccess", UPDATE_USER_FAIL: "HomeActions.updateUserFail", LOGOUT_SUCCESS: "HomeActions.logoutSuccess"…}
GET_USER : "HomeActions.getUser"
LOGOUT : "HomeActions.logout"
LOGOUT_FAIL : "HomeActions.logoutFail"
LOGOUT_SUCCESS : "HomeActions.logoutSuccess"
UPDATE_USER_FAIL : "HomeActions.updateUserFail"
UPDATE_USER_SUCCESS : "HomeActions.updateUserSuccess"
getUser : action()
logout : action()
logoutFail : action()
logoutSuccess : action()
updateUserFail : action()
updateUserSuccess : action()
__proto__ : Object
Clearly there is no dispatching method in the newer version. Can somebody explain why is this so?
I've managed to get Nunjucks working with Sails.js, however it seems that the changes are not being picked up until I restart the server. I'll automatically see the changes reflected once or twice, but after that, even manually refreshing the browser will not show my changes.
I implemented LiveReload with the advice here:
Get livereload to work with Sails.js
but I don't suspect it's an issue with LiveReload.
Has anyone else gotten Sails.js and Nunjucks to play nicely together? If so, how?
The problem is nunjucks itself. It has a watch option which by default is set to false:
You can enable it in sails/config/bootstrap.js:
var nunjucks = require('nunjucks')
module.exports.bootstrap = function(cb) {
nunjucks.configure({
watch:true
})
// It's very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
cb();
};
In combination with the livereload everything works fine.
in /config/views.js
engine: {
ext: 'html',
fn: function (str, options, fn) {
var engine = require('nunjucks');
engine.configure('views', {
autoescape : true,
throwOnUndefined : true,
trimBlocks : true,
lstripBlocks : true,
express : sails.hooks.http.app,
watch : true,
noCache : false,
web : {
useCache : true,
async : false
}
});
engine.render(str, options, fn);
}
},
For Sails.js 1 the solution has slightly changed:
In /config/views.js
module.exports.views = {
...
getRenderFn: () => {
// Import nunjucks.
const nunjucks = require('nunjucks');
// Configure nunjucks.
const env = nunjucks.configure('views', {
autoescape : false,
throwOnUndefined : true,
trimBlocks : true,
lstripBlocks : true,
watch : true,
noCache : false,
web : {
useCache : true,
async : false
}
});
// Here you can add filter
env.addFilter('filtername', (name) => {
return name;
});
return nunjucks.render;
}
}
Hope this will help someone ;)