While loop is not generating data randomly - javascript

I'm creating API tests with async-await using Supertest and Mocha.
In the accountsData.js file I created a function to generate random test accounts.
In the accountsHelper.js file I created a function to create unlimited accounts using a while loop
When I run tests on the post_accounts.js file, the first account is created successfully, but from the second account, the data generated in the accountsData.js file is already repeated.
Why isn't data randomly generated when I create more than one account using data from the accountsData.js file?
accountsData.js
const casual = require('casual');
function randomAccount() {
return {
'email': casual.email,
'password': '123456',
};
}
module.exports = {
randomAccount,
};
accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
/* eslint-disable no-console */
const accountList = [];
let counterAccounts;
module.exports = {
async createAccount(account, accountsToCreate = 2, validateResponse = true) {
counterAccounts = 0;
while (counterAccounts < accountsToCreate) {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
.send(account);
if (validateResponse === true) {
if (res.status === commonData.statusCode.ok) {
accountList.push(res.body);
} else {
throw new Error('Email already exists\n\n' + JSON.stringify(res.body, null, ' '));
}
} else {
return res.body;
}
} catch (err) {
console.log(err);
}
counterAccounts++;
}
return accountList;
},
};
post_accounts.js
const accountsData = require('../../data/accountsData');
const accountsHelper = require('../../helpers/accountsHelper');
const account = accountsData.randomAccount();
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async() => {
const res = await accountsHelper.createAccount(account);
// eslint-disable-next-line no-console
console.log(res);
});
});
});
API response:
Create accounts with email and password
valid accounts
Error: Email already exists
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `account` instance is not valid. Details: `email` Email already exists (value: \"Lemuel.Lynch#Susan.net\").",
"details": {
"context": "account",
"codes": {
"email": [
"uniqueness"
]
},
"messages": {
"email": [
"Email already exists"
]
}
}
}
}
at Object.createAccount (/Users/rafael/Desktop/projects/services/test/helpers/accountsHelper.js:24:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ { 'privacy-terms': false,
'created-date': '2019-08-24T10:00:34.094Z',
admin: false,
isQueued: false,
lastReleaseAttempt: '1970-01-01T00:00:00.000Z',
'agreed-to-rules': { agreed: false },
email: 'Lemuel.Lynch#Susan.net',
id: '5d610ac213c07d752ae53d91' } ]
✓ should create an account successfully (2243ms)
1 passing (2s)

The code that you posted doesn't correspond to the code that you're describing in prose.
However, I tested your accountsData.js file, in the way that your words (but not your code) say that you're using it, and it works fine.
// main.js
const { createPerson } = require(__dirname + '/accountsData')
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
Output from running it once:
$ node main.js
{ email: 'Anne_Ebert#Macie.com', password: '123456' }
{ email: 'Manley.Lindgren#Kshlerin.info', password: '123456' }
{ email: 'McClure_Thurman#Zboncak.net', password: '123456' }
{ email: 'Breitenberg.Alexander#Savannah.com', password: '123456' }
{ email: 'Keely.Mann#Stark.io', password: '123456' }
And again:
$ node main.js
{ email: 'Destany_Herman#Penelope.net', password: '123456' }
{ email: 'Narciso_Roob#gmail.com', password: '123456' }
{ email: 'Burnice_Rice#yahoo.com', password: '123456' }
{ email: 'Roma_Nolan#yahoo.com', password: '123456' }
{ email: 'Lilla_Beier#yahoo.com', password: '123456' }
Nothing in the code that you posted is actually requiring or using accountsData.js. If you change your code to use it, I think you'll see, like I do, that it works.

Problem is, you are generating the random account and storing it in a variable 'post_accounts.js(line 3)'. So, when you create an account, you are using the same payload to create multiple accounts, which obviously throws an error.
I just modified the accountHelper to properly handle your scenario. Hope this helps.
Note: The code is not tested, I just wrote it from my mind. Please test and let me know if it works.
// accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
const accountsData = require('../../data/accountsData');
/* eslint-disable no-console */
const accountList = [];
module.exports = {
async createAccount(account, accountsToCreate = 1, validateResponse = true) {
// creates an array of length passed in accountsToCreate param
return (await Promise.all(Array(accountsToCreate)
.fill()
.map(async () => {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
// takes account if passed or generates a random account
.send(account || accountsData.randomAccount());
// validates and throw error if validateResponse is true
if (validateResponse === true && (res.status !== commonData.statusCode.ok)) {
throw new Error(
'Email already exists\n\n' +
JSON.stringify(res.body, null, ' ')
);
}
// return response body by default
return res.body;
} catch (e) {
console.error(e);
// return null if the create account service errors out, just to make sure the all other create account call doesnt fail
return null;
}
})))
// filter out the null(error) responses
.filter(acc => acc);
}
};
//post_accounts.js
const accountsHelper = require('../../helpers/accountsHelper');
const accountsData = require('../../data/accountsData');
const GENERATE_RANDOM_ACCOUNT = null;
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async () => {
const result = await accountsHelper.createAccount();
expect(result.length).toEquals(1);
});
it('should create 2 accounts successfully', async () => {
const result = await accountsHelper.createAccount(GENERATE_RANDOM_ACCOUNT, 2);
expect(result.length).toEquals(2);
});
it('should not create duplicate accounts', async () => {
const account = accountsData.randomAccount();
// here we are trying to create same account twice
const result = await accountsHelper.createAccount(account, 2);
// expected result should be one as the second attempt will fail with duplicate account
expect(result.length).toEquals(1);
});
});
});

Related

How to get specific property of an object?

So I'm sending data properly to mongo and data (user input information), which is correctly held in backend. In console I'm getting interceptor that tells me that data is received from Mongo DB, but how to properly get those properties (user's email, title of photo and url blob) or 'data'? So it can be seen as individual data (email, title...) and not as the whole object like it can be seen in console now.
--THIS IS IN MY VUE--
dohvatiObjavu(){
this.objava = Objave.dohvati_objavu();
console.log("Current post " + this.objava);
}
},
-- THIS IS IN SERVICES--
[let Objave = {
async dohvati_objavu() {
let response = await Service.get(/galerija)
let data = response.data;
console.log("Current posts in services: "+data.naslov)
return {
id: data._id,
email: data.email,
naslov: data.naslov,
noviOpisSlike: data.noviOpisSlike,
slika: data.slikaReference,
}
},
}
--THIS IS IN BACKEND--
app.get ('/galerija', async (req , res) => {
let db = await connect();
let cursor = await db.collection('galerija').find();
let results = await cursor.toArray();
res.json(results);
});
-- MY CONSOLE--
Objave.dohvati_objavu(); is an async function. So you should also await this inside your Vue method dohvatiObjavu().
I created a simplified working example, based on your code:
const Objave = {
dohvati_objavu: async function() {
// mock Service.get(/galerija) with Promise.resolve
const data = await Promise.resolve({
id: 'mockId',
email: 'mockEmail',
naslov: 'mockNaslov',
noviOpisSlike: 'mockNoviOpisSlike',
slika: 'mockSlika',
});
return {
id: data._id,
email: data.email,
naslov: data.naslov,
noviOpisSlike: data.noviOpisSlike,
slika: data.slikaReference
}
}
}
const MyVueComponent = class {
objava = undefined;
// DOES NOT WORK
dohvatiObjavu() {
this.objava = Objave.dohvati_objavu();
console.log("[dohvatiObjavu] Current post ", this.objava);
}
// WORKS
async dohvatiObjavu2() {
this.objava = await Objave.dohvati_objavu(); // <!-- await
console.log("[dohvatiObjavu2] Current post ", this.objava);
}
}
const component = new MyVueComponent()
component.dohvatiObjavu();
component.dohvatiObjavu2();

Valdaition for user exist or not using nodejs

I'm working on a project in React and ran into a problem that has me stumped.
I want to add new user but want to check if user is present or not I tried to give custom message but still not giving me my custom message.
so here is my code and i am not able to figure out how to give custom message.
if any one have some solution it will be really great if you help me
const Employee = require("../models/employeeSchema");
//custom imports
const AppError = require("../helpers/appErrorClass");
const sendErrorMessage = require("../helpers/sendError");
const sendResponse = require("../helpers/sendResponse");
const addEmployees = async (req, res, next) => {
try {
let data = req.body;
let newEmployee = {};
newEmployee.firstName = data.firstName.trim();
newEmployee.lastName = data.lastName.trim();
newEmployee.company = data.company.trim();
newEmployee.email = data.email.trim();
newEmployee.contact = data.contact;
newEmployee.skills = data.skills.split(",").map((skill) => {
return skill.trim();
});
newEmployee.altDescription = data.altDescription.trim();
newEmployee.hobbies = data.hobbies.split(",").map((hobby) => {
return hobby.trim();
});
newEmployee.socialLinks = [
{
gitHub: data.gitHub,
linkedIn: data.linkedIn,
website: data.website,
},
];
newEmployee.imageUrl = req.image;
let employee = await Employee.find({ email: newEmployee.email });
if (employee.email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
} else {
let data = await Employee.create(newEmployee);
sendResponse(200, "Employee added Succesfully", data, req, res);
}
} catch (err) {
return sendErrorMessage(new AppError(400, "unsuccessful", err), req, res);
}
};
module.exports.addEmployees = addEmployees;
I have no idea why this is happening, if anyone has experienced this I would be grateful.
Edit:
console.log(employee) outputs the following:
[{
employeeId: 'c88wgb4ocuw01609613746852',
contact: 123456789,
imageUrl: 'http://res.cloudinary.com/altafshaikh/image/upload/v1609613765/qbl7ujyz0wi6cy0xt3rf.jpg',
skills: [ 'sleep', 'laziness' ],
altDescription: 'Hello Saurav',
hobbies: [ 'Nautanki', 'doubtfull' ],
socialLinks: [ {} ],
_id: 5ff0c1c5327f300a55f6259a,
firstName: 'Saurav',
lastName: 'Upadhyay',
company: 'Raw',
email: 'sourav23#gmail.com',
__v: 0
}]
It's because employee is an array. You need to access the first element.
if (employee.length && employee[0].email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}
Since the db query condition is email, we can assume that it will return empty array if no matches are found. It also means that the array will be populated only if a match is found. So we can also avoid the unnecessary check of emails being equal. You can do this.
if (employee.length) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}

Firebase Permission denied Error on Firebase emulator

I am referencing this tutorial for Firestore security rules. I have extracted the code from the repository and it matches that of the video.
I changed the setup code to run the firestore.rules instead of firestore-test.rules, and tried running firebase emulators:start and jest ./spec following the same directory structure, I fail the tests of "should allow delete when user is admin" and "should not allow delete for normal user" and the reason it is failing is due to the write rule in the wildcard. Does anyone know what is wrong?
collections.spec.js
const { setup, teardown } = require("./helpers");
describe("General Safety Rules", () => {
afterEach(async () => {
await teardown();
});
test("should deny a read to the posts collection", async () => {
const db = await setup();
const postsRef = db.collection("posts");
await expect(postsRef.get()).toDeny();
});
test("should deny a write to users even when logged in", async () => {
const db = await setup({
uid: "danefilled"
});
const usersRef = db.collection("users");
await expect(usersRef.add({ data: "something" })).toDeny();
});
});
describe("Posts Rules", () => {
afterEach(async () => {
await teardown();
});
test("should allow update when user owns post", async () => {
const mockData = {
"posts/id1": {
userId: "danefilled"
},
"posts/id2": {
userId: "not_filledstacks"
}
};
const mockUser = {
uid: "danefilled"
};
const db = await setup(mockUser, mockData);
const postsRef = db.collection("posts");
await expect(
postsRef.doc("id1").update({ updated: "new_value" })
).toAllow();
await expect(postsRef.doc("id2").update({ updated: "new_value" })).toDeny();
});
test("should allow delete when user owns post", async () => {
const mockData = {
"posts/id1": {
userId: "danefilled"
},
"posts/id2": {
userId: "not_filledstacks"
}
};
const mockUser = {
uid: "danefilled"
};
const db = await setup(mockUser, mockData);
const postsRef = db.collection("posts");
await expect(postsRef.doc("id1").delete()).toAllow();
await expect(postsRef.doc("id2").delete()).toDeny();
});
test("should allow delete when user is admin", async () => {
const mockData = {
"users/filledstacks": {
userRole: "Admin"
},
"posts/id1": {
userId: "not_matching1"
},
"posts/id2": {
userId: "not_matching2"
}
};
const mockUser = {
uid: "filledstacks"
};
const db = await setup(mockUser, mockData);
const postsRef = db.collection("posts");
await expect(postsRef.doc("id1").delete()).toAllow();
});
test("should not allow delete for normal user", async () => {
const mockData = {
"users/filledstacks": {
userRole: "User"
},
"posts/id1": {
userId: "not_matching1"
},
"posts/id2": {
userId: "not_matching2"
}
};
const mockUser = {
uid: "filledstacks"
};
const db = await setup(mockUser, mockData);
const postsRef = db.collection("posts");
await expect(postsRef.doc("id1").delete()).toDeny();
});
test("should allow adding a post when logged in", async () => {
const db = await setup({
uid: "userId"
});
const postsRef = db.collection("posts");
await expect(postsRef.add({ title: "new_post" })).toAllow();
});
test("should deny adding a post when not logged in", async () => {
const db = await setup();
const postsRef = db.collection("posts");
await expect(postsRef.add({ title: "new post" })).toDeny();
});
});
firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// lock down the db
match /{document=**} {
allow read: if false;
allow write: if false;
}
match /posts/{postId} {
allow update: if userOwnsPost();
allow delete: if userOwnsPost() || userIsAdmin();
allow create: if loggedIn();
}
function loggedIn() {
return request.auth.uid != null;
}
function userIsAdmin() {
return getUserData().userRole == 'Admin';
}
function getUserData() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data
}
function userOwnsPost() {
return resource.data.userId == request.auth.uid;
}
}
}
Error trace from terminal
FirebaseError: 7 PERMISSION_DENIED:
false for 'create' # L10
● Posts Rules › should not allow delete for normal user
FirebaseError: 7 PERMISSION_DENIED:
false for 'create' # L10
at new FirestoreError (/Users/../../../../../../../../../Resources/rules/node_modules/#firebase/firestore/src/util/error.ts:166:5)
at ClientDuplexStream.<anonymous> (/Users/../../../../../../../../../Resources/rules/node_modules/#firebase/firestore/src/platform_node/grpc_connection.ts:240:13)
at ClientDuplexStream._emitStatusIfDone (/Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client.js:234:12)
at ClientDuplexStream._receiveStatus (/Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client.js:211:8)
at Object.onReceiveStatus (/Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client_interceptors.js:1311:15)
at InterceptingListener._callNext (/Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client_interceptors.js:618:8)
at /Users/../../../../../../../../../Resources/rules/node_modules/grpc/src/client_interceptors.js:1127:18
I actually followed the same tutorial to get started with the firebase emulator and got the same kind of error messages. The problem for me was that when you start the simulator it automatically looks for your firestore.rules file and loads the rules. So, when you then add your mockData the rules already apply.
In order to make your test code work either change the setting for your firestore rules file in your firebase.json to a non-existing file (or rules file that allows all read/write) or add the mockData as an admin in your setup function, e.g.:
module.exports.setup = async (auth, data) => {
const projectId = `rules-spec-${Date.now()}`;
const app = firebase.initializeTestApp({
projectId,
auth
});
const db = app.firestore();
// Initialize admin app
const adminApp = firebase.initializeAdminApp({
projectId
});
const adminDB = adminApp.firestore();
// Write mock documents before rules using adminApp
if (data) {
for (const key in data) {
const ref = adminDB.doc(key);
await ref.set(data[key]);
}
}
// Apply rules
await firebase.loadFirestoreRules({
projectId,
rules: fs.readFileSync('firestore.rules', 'utf8')
});
return db;
};
Hope this helps.
Also see this question
For those that are currently having this issue firestore 8.6.1 (or equivalent), there is a bug discussed here:
https://github.com/firebase/firebase-tools/issues/3258#issuecomment-814402977
The fix is to downgrade to firestore 8.3.1, or if you are reading this in the future and firestore >= 9.9.0 has been released, upgrade to that version.

Getting empty response while doing async and await

I am new to node.js and javascript. I get confused in my code as It give me empty response. I am trying to implement the promise and async and await feature however getting respones {}.
Could anybody help me to understand where I am wrong.
Please see below code may be it will long however I need help on issue of await where I am not getting empty result
var response = {};
var newSecret ='';
class FabricClientRegister {
constructor() {
console.log("called constructer");
}
async RegisterUser(Username, roleid) {
try {
const setAsyncTimeout = (cb, timeout = 0) => new Promise(resolve => {
setTimeout(() => {
cb();
resolve();
}, timeout);
});
let query1 = {}
query1.RoleID = roleid;
// query1.name = '';
var name ='';
console.log('roleid',roleid)
// console.log('Username',Username);
var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('./config/Config.json', 'utf8'));
// var Username = req.body.username;
console.log('Username',Username)
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(Username);
if (userExists) {
response.data = null;
response.httpstatus = 400;
response.message = `An identity for the ${Username} already exists in the wallet`;
return response;
}
console.log("Username1",Username)
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.exists(appAdmin);
if (!adminExists) {
response.data = null;
response.httpstatus = 400;
response.message = "Am admin identity is not registered . please register admin first";
return response;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: appAdmin, discovery: { enabled: false, asLocalhost: true }
/*** Uncomment lines below to disable commit listener on submit ****/
, eventHandlerOptions: {
strategy: null
}
});
// Get the CA client object from the gateway for interacting with the CA.
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
console.log("Username4",Username)
MongoClient.connect(config.Database.DFARM.connectString, async function (err, client) {
if (err) {
let connError = new Error(500, "Error connecting to DFARM database", err);
res.status(connError.status).json(connError);
}
else {
client.db(config.Database.DFARM.dbName).collection("Role").find(query1).toArray(function (err, docs) {
if(err) {
console.log('err db',err);
} else{
console.log('Role name DB',docs);
name = docs[0].name;
query1.name = name;
console.log('Role',query1);
}
client.close();
})
}
})
setTimeout(() => console.log('Role 10',query1.name), 5 * 1000);
const doStuffAsync = async () => {
setAsyncTimeout( async () => {
console.log('Role Name',query1.name);
const secret = await ca.register({enrollmentID: Username, role: query1.name}, adminIdentity);
console.log('secret',secret);
response.secret = secret;
newSecret = secret;
console.log('newSecret', newSecret );
response.httpstatus = 200;
response.message = `Successfully registered admin user ${Username} and imported it into the wallet`;
return response;
}, 10000);
};
doStuffAsync();
// .then(function(result) {
// // console.log('promise result',result) // error here undefined
// }).catch(err)
// {
// console.log("eee", err)
// };
console.log('newSecret1', newSecret)
console.log('respones', response)
return newSecret;
} catch (error) {
response.error = error;
response.httpstatus = 500;
response.message = "Failed to enroll admin due to above error";
return response;
}
}
};
Please see below output in CLI
Username Abhinav345
called constructer
roleid 1
Username Abhinav345
Wallet path: /vagrant/Dfarm-app/dFarmUserService/dFarmUserService/wallet
Username1 Abhinav345
Username4 Abhinav345
newSecret1
respones {} //getting empty one however need some data
data result
Role name DB [ { _id: 5d029dec7e8409b489e04cff,
appName: 'Farmer',
RoleID: 1,
name: 'farmer',
routes: [ [Object], [Object], [Object], [Object] ],
tabs: [ [Object], [Object], [Object], [Object] ] } ]
Role { RoleID: 1, name: 'farmer' }
Role 10 farmer
Role Name farmer
secret XXCephExVetS
newSecret XXCephExVetS
Maybe you should consider put await before doStuffAsync().

Joi custom validation

I'm using Joi to validate some data from user. I'm using it with module like this:
const Joi = require('joi')
// User validation rules
module.exports = {
create: {
body: {
email: Joi.string().email().required(),
password: Joi.string().min(6).max(128).required(),
name: Joi.string().max(128).required()
}
},
update: {
body: {
password: Joi.string().min(6).max(128).required(),
name: Joi.string().max(128).required()
}
}
}
and then in router I'm passing it as middleware:
router.post('/register', validator(create), userController.register)
For update I want to create custom validator with code like this:
const json = {
"email":"aa#aa.pl",
"password":"someNewPass",
"name":"John Smith",
"activationKey":"123123",
"active":false,
"resetPasswordKey":"123123"
}
const forbiddenFields = ["email", "activationKey", "active", "resetPasswordKey"];
const validate = (json, forbidden) => {
for(let i = 0; i < forbidden.length; i++) {
if(json.hasOwnProperty(forbidden[i])) {
return false;
}
}
return true;
}
const isValid = validate(json, forbiddenFields)
console.log('is json valid? ', isValid)
I found extend method in Joi API but example is so confusing that I can not handle to create custom validation with my code.
You may want to use forbidden keys.
const input = {
email: 'example#example.com',
activationKey: 123
};
const schema = {
email: Joi.string().email(),
activationKey: Joi.any().forbidden()
};
const result = Joi.validate(input, schema);
if (result.error) {
console.log(result.error.details)
}
<script src="https://cdn.jsdelivr.net/npm/joi-browser#13.4.0/dist/joi-browser.min.js"></script>

Categories