Javascript function evaluation? - javascript

const debugMode = true;
// if "isCritical" is true, display the message regardless of
// the value of debugMode
function logger(message, isCritical) {
if (isCritical) console.log(message);
else if (debugMode) console.log(message);
}
In the above function, if I issued the following command, would the UTIL. inspect function evaluate "myObj" and not pass the data? I'd preferably not want UTIL.inspect to invoke if "isCritical" is set to false.
logger(
"myObj =\n" +
UTIL.inspect(myObj, {
showHidden: false,
depth: null
}),
false
);
Is there a way to avoid the evaluation of the first parameter in the function when the second parameter is false?

Seperate your code for logging from the decision wether or not it should be executed.
And use a build pipeline that supports tree-shaking.
Live example on rollupjs.org
// config.js
export const DEBUG = false;
// logging.js
import { DEBUG } from "./config.js";
export const log = console.log; // or whatever
export const debug = DEBUG ? (...args) => logger("debug:", ...args) : () => void 0;
// main.js
import { DEBUG } from "./config.js";
import { log, debug } from "./logging.js";
log("this will always be logged");
if (DEBUG) {
log("This will be eliminated when DEBUG=false")
}
// or more concise:
DEBUG && log(`This can be eliminated ${window.location = "/side-effect"}`);
debug("This approach works for simple things: " + location);
debug(`But it has limits ${window.location = "/side-effect"} :(`);

Related

Jest how to change global variable to cover all branches

// target.js
const urlPrefix = IS_TEST_ENV || _DEV_ ? 'https://xxx/cms/media/' : 'https://zzz/cms/media/';
const formatImageSizeUrl = (url, size) => {
if (!/\d+x\d+/.test(size)) {
return url;
}
if (url.startsWith(urlPrefix)) {
return `${url}?d=${size}`;
}
return url;
};
...
// jest.config.js
module.exports = {
globals: {
IS_TEST_ENV: true,
_DEV_: true
}
}
how to change IS_TEST_ENV and DEV into false temporarily.so can cover all branches
My opinion on this is that your code has some logic that needs mocking, but that logic is implicit and not currently mockable. I would refactor the code as follows:
// settings.js
// Check whether we are on a production environment or not
export const isProd = () => !(IS_TEST_ENV || _DEV_)
// target.js
// Reversed order of URLs as the boolean expression returns true if we are in production
const urlPrefix = isProd() ? 'https://zzz/cms/media/' : 'https://xxx/cms/media/';
// target.test.js
// Mock out isProd() to return true, as by default it will be false
jest.mock('../settings', () => {
isProd: () => true
})
// Run test to ensure we are getting the right URL
The upside to this approach is that you have a single canonical source of whether you're in production or not, which is useful if you wind up needing to make that check in multiple places. You also only need to mock out or update one method if you want to change this behaviour in the future.

How to pass K6 Tool data modified in default function to teardown stage

K6 Tool is being used for our testing needs. For the sample snippet below when run with K6, we see that the change occurred in default function for data passed from setup is not affected and visible in tear down stage. Is there any other possible way to have this available so that we could utilize it for Test Data Management purposes during Load Tests?
import http from "k6/http";
import { group, check, sleep, fail } from "k6";
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";
const SLEEP_DURATION = 1;
// Global variables should be initialized.
var csvData = [{"Id":"P976O6RP8NSFN076RKLBSGK1Q8NZT7WA"},{"Id":"D4YJZFQJUPJTZWPLP2VB5M839SZBNNSO"}];
function removeId(arr, value) {
arr = arr.filter(function(item) {
return item.Id !== value
});
return arr;
}
export function setup() {
return JSON.parse(JSON.stringify(csvData));
}
export default function(data) {
let Id = csvData[0].Id;
data = removeId(data, Id);
console.log('ID deleted is: '+Id+' \nJson<data> in default :: '+JSON.stringify(data));
}
export function handleSummary(data) {
return {
//stdout: JSON.stringify(data),
};
}
export function teardown(data) {
//Teardown does not have modified data object updated in default function
console.log('\nJson<data> in teardown :: '+JSON.stringify(data));
}
No, this is (currently?) not possible. The setup data must not be modified by the default function. Think about it: this wouldn't work, if executed in a cloud or clustered environment, because the setup and default function might be executed on different machines.
Why do you want to modify the setup data?

Accessing non-existent property of module.exports inside circular dependency NodeJS

Im having some issues when using module.exports inside NodeJS, and I've followed multiple guides, and im almost certain Im doing it right.
I have to scripts, main.js and event.js. Im trying to share a function from main.js to event.js, but its not working. Here is the code:
Main.js
function Scan(){
if(fs.readdirSync('./events/').length === 0){
console.log(colors.yellow('Events Folder Empty, Skipping Scan'))
} else {
var events = fs.readdirSync('./events/').filter(file => file.endsWith('.json'))
for(const file of events){
let rawdata = fs.readFileSync('./events/' + file);
let cJSON = JSON.parse(rawdata);
}
events.sort()
tevent = events[0]
StartAlerter()
}
}
module.exports = { Scan };
Event.js
const main = require('../main')
main.Scan;
This returns the error:
(node:19292) Warning: Accessing non-existent property 'Scan' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
What am I doing wrong?
I discovered that the arrangement had no effect in the error.
I simply changed the way I exported the function from the Main.js
from:
module.exports = { Scan };
to:
exports.Scan = Scan
And in Event.js, I was able to access the file like this
const main = require("./Main.js");
let result = main.Scan();
This solved my problem, I hope it helps another developer 😎
Problem solved, heres what I did differently:
module.exports = { Scan };
Is declared before the Scan function is defined, like so:
module.exports = { Scan };
function Scan(){
//Code
}
Then in event.js, I wrote
const main = require('../main')
As it is now a module, and can be used with the require() function.
Then to execute the funciton in event.js, I write
main.Scan()
To execute it.
better try :
module.exports = Scan;
I am gonna answer it using a simple example, like in this case below:
File A has 3 functions to process database activity: function
addDB, updateDB, and delData;
File B has 2 functions to process User activity on smartphone:
function addHistory, and editHistory;
Function updateDB in file A is calling function editHis in file B, and function editHistory is calling function updateDB in file A. This is what we called circular-dependency. And we need to prevent it by only giving output of state from editHistory and the rest will be processed inside file A.
//ORIGINAL FUNCTIONS which caused CIRCULAR DEPENDENCY
function updateDB() {
//process update function here
//call function in fileB
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
response = {
state: 1,
message: "success",
};
}
});
return response;
}
//THIS is the WRONG ONE
function editHistory() {
//process function to edit History here
//call function in fileA
const file = require("fileA.js");
await file.updateDB(data).then((output) => { //You should not call it here
if(output["message"] === "success") {
output = {
state: 1,
message: "success",
};
}
});
return output;
}
//==================================================//
//THE FIX
function updateDB() {
//process function here
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
await updateDB(data).then((output) => {
response = {
state: 1,
message: "success",
};
});
} else {
log("Error");
}
});
return response;
}
function editHistory() {
//process function to edit History here
// No more calling to function inside the file A
output = {
state: 1,
message: "success",
};
return output;
}

Mock an import from another file but still return a mock value

I'm testing a function which calls another function imported from anotherFile. That outsideFunc returns an object which contains 'name'. I need this to exist in order to progress through the rest of my test/the function to work correctly.
systemUnderTest.js
import { outsideFunc } from './anotherFile.js';
function myFunc() {
const name = outsideFunc().name;
}
anotherFile.js:
export function outsideFunc() {
return { name : bob }
}
I don't care about testing anotherFile or the result of outsideFunc, but I still need to return a mock value as part of testing myFunc;
systemUnderTest.spec.js
describe("A situation", () => {
jest.mock("./anotherFile", () => ({
outsideFunc: jest.fn().mockReturnValue({
name: 'alice'
})
}));
it("Should continue through the function steps with no problems", () => {
expect(excludeCurrentProduct(initialState)).toBe('whatever Im testing');
});
});
The problem I get is that, when the unit test is working through myFunc, const name returns undefined where it should return alice. I would expect it to get the data from my jest.mock of the anotherFile file and its mock exported function, but it doesn't get the right response.
When I asset that I expect name = alice I actually get name = undefined.
systemUnderTest.js
import { outsideFunc } from './anotherFile.js';
// let's say that the function is exported
export function myFunc() {
const name = outsideFunc().name;
// and let's say that the function returns the name
return name;
}
you can describe in your
systemUnderTest.spec.js
import { myFunc } from './systemUnderTest';
import { outsideFunc } from './anotherFile';
// using auto-mocking has multiple advantages
// for example if the outsideFunc is deleted the test will fail
jest.mock('./anotherFile');
describe('myFunc', () => {
describe('if outsideFunc returns lemons', () => {
outsideFunc.mockReturnValue({name: 'lemons'});
it('should return lemons as well', () => {
expect(myFunc()).toEqual('lemons');
});
});
});
working example

Use chance plugin in cypress

Is it possible to use chance plugin with cypress.io?
https://chancejs.com
I installed plugin via npm to node_modules\chance and edited /plugins/index.js file, but still get error from cypress - Can't start, The plugins file is missing or invalid.
If using this plugin is impossible - what do you recommend to write tests basing on registration new users? I planned to use chance to generate "random: emails and passwords.
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = on => {
on("task", {
chance: require("chance"),
});
};
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
Just install chancejs with npm:
npm install chance
Then just use it in your test for example:
/// <reference types="cypress" />
import Chance from 'Chance';
const chance = new Chance();
describe('Testing chance', function (){
const company =chance.company();
it('type company in duckduckgo.com', function () {
cy.visit('https://duckduckgo.com/')
cy.get('#search_form_input_homepage')
.should('be.visible')
.type(company)
})
})
cypress/support/index.js:
Override the default task command so that you can supply multiple arguments as you'd normally.
Cypress.Commands.overwrite('task', (origFn, name, ...args) => {
return origFn(name, args);
});
// if you're gonna use `chance` plugin a lot, you can also add a custom command
Cypress.Commands.add('chance', (...args) => {
return cy.task('chance', ...args);
});
cypress/plugins/index.js:
Wrap the tasks in function that will spread the arguments, and also handle a case when the task doesn't return anything and return null instead, so that cypress doesn't complain.
const chance = require('chance').Chance();
// lodash should be installed alongside with cypress.
// If it doesn't resolve, you'll need to install it manually
const _ = require('lodash');
on('task', _.mapValues(
{
chance ( method, ...args ) {
return chance[method](...args);
}
},
func => args => Promise.resolve( func(...args) )
// ensure we return null instead of undefined to satisfy cy.task
.then( val => val === undefined ? null : val )
));
In your spec file:
describe('test', () => {
it('test', () => {
cy.document().then( doc => {
doc.body.innerHTML = `<input class="email">`;
});
cy.task('chance', 'email', {domain: 'example.com'}).then( email => {
cy.get('.email').type(email);
});
// or use the custom `chance` command we added
cy.chance('email', {domain: 'test.com'}).then( email => {
cy.get('.email').type(email);
});
});
});

Categories

Resources