How to use the beforeEach in node-tap? - javascript

Can someone provide an example on how to use the beforeEach? http://www.node-tap.org/api/
Ideally, an example of the promise version, but a callback version example would also be nice.
Here is a test I created which works fine:
'use strict';
const t = require('tap');
const tp = require('tapromise');
const app = require('../../../server/server');
const Team = app.models.Team;
t.test('crupdate', t => {
t = tp(t);
const existingId = '123';
const existingData = {externalId: existingId, botId: 'b123'};
const existingTeam = Team.create(existingData);
return existingTeam.then(() => {
stubCreate();
const newId = 'not 123'
const newData = {externalId: newId, whatever: 'value'};
const newResult = Team.crupdate({externalId: newId}, newData);
const existingResult = Team.crupdate({externalId: existingId}, existingData);
return Promise.all([
t.equal(newResult, newData, 'Creates new Team when the external ID is different'),
t.match(existingResult, existingTeam, 'Finds existing Team when the external ID exists')
]);
});
})
.then(() => {
process.exit();
})
.catch(t.threw);
function stubCreate() {
Team.create = data => Promise.resolve(data);
}
Before I do anything, I want to persist existingTeam. After it's saved, I want to stub Team.create. After these two things, I want to start actually testing. I think it would be cleaner if instead of using a Promise.all or perhaps duplicating the test code, I could use beforeEach.
How would I convert this to use beforeEach? Or what is an example of its usage?

Simple, just return promise from callback function
const t = require('tap');
const tp = require('tapromise');
const app = require('../../../server/server');
const Team = app.models.Team;
const existingId = '123';
const existingData = {
externalId: existingId,
botId: 'b123'
};
t.beforeEach(() => {
return Team.create(existingData).then(() => stubCreate());
});
t.test('crupdate', t => {
t = tp(t);
const newId = 'not 123'
const newData = {
externalId: newId,
whatever: 'value'
};
const newResult = Team.crupdate({
externalId: newId
}, newData);
const existingResult = Team.crupdate({
externalId: existingId
}, existingData);
return Promise.all([
t.equal(newResult, newData, 'Creates new Team when the external ID is different'),
t.match(existingResult, existingTeam, 'Finds existing Team when the external ID exists')
]);
}).then(() => {
process.exit();
}).catch(t.threw);
function stubCreate() {
Team.create = data => Promise.resolve(data);
}

Related

Add documentID of fetched document to array in firebase cloud function

I have a cloud function that "Joins" data from a list of documents in a collection.
I then return the result as an array, but I want to return the documentId as well (doc.id) in the list that i return.
How can i do that?
const restData = [];
//const userId = ctx.auth.uid;
const userId = 'dHAP1CNN6LhJWddQoTqyIkqIjhB2'; // !!! TEST ONLY
const all = await db.collection(`/customers/${userId}/lunch_cards`).listDocuments().then((snapshot) => {
snapshot.forEach(doc => {
const nextData = db.collection(`/restaurants`).doc(doc.id).get();
const newData = {...nextData, documentId: doc.id}; <-- This does not work only documentId isout in newData
console.log(util.inspect(newData));
restData.push(nextData);
console.log(doc.id);
});
});
const snaps = await Promise.all(restData);
const responseArray = snaps.map((s) => {return s.data()});
return responseArray;
I solved it!
Solution:
Just adding a new string to the array :)
const responseArray = snaps.map((s) => {
const snapData = s.data();
if (snapData) {
snapData['id'] = s.id;
}
return snapData;
});

Delete Function using .filter Method

I am creating a note taking app and am getting stuck on my deleteNote function. I am needing to use the .filter method to remove notes w/ an assigned id and keep the ones not associated to that id. Here is my code so far.
const fs = require("fs");
const util = require("util");
// returns a unique ID for our returns
const uuidv1 = require("uuid/v1");
// creates a promified version of fs.readfile and writefile
const readFileAsync = util.promisify(fs.readfile);
const writeFileAsync = util.promisify(fs.writefile);
class Store {
read() {
return readFileAsync("./db/db.json", "utf8");
}
write(note) {
return writeFileAsync("./db/db.json", JSON.stringify(note));
}
getNotes() {
return this.read().then(notes => {
let parsedNotes;
try {parsedNotes = [].concat(JSON.parse(notes))}
catch (err) {
parsedNotes = [];
}
return parsedNotes;
})
}
// example of destructuring -- im taking the title, text string and destructuring it to add a unique id.
addNote(note) {
const {title, text} = note;
const newNote = {title, text, id: uuidv1()};
return this.getNotes()
.then(notes => [...notes, newNote]);
.then(updatedNotes => this.write(updatedNotes));
.then(() => newNote);
}
// delete note is going to take in an id and use a .filter to only keep the notes that do not include that id.
deleteNote() {
}
}
module.exports = new Store();
You already know you're filtering, so just do it:
deleteNote(id) {
return this.getNotes()
.then(notes => notes.filter(note => note.id !== id))
.then(updatedNotes => this.write(updatedNotes));
}
Try this one which includes returning deleted note.
async deleteNote(id) {
const notes = await this.getNotes();
const filtered = notes.filter((note) => note.id !== id);
await this.write(filtered);
const deleted = notes.filter((note) => note.id === id);
return deleted;
}

Trouble understanding Cloud Function Error

I am new to cloud funcations node.js and type script. I am running the below code and getting the error below and can't make sense of it after watch a ton of videos about promises and searching other questions.
any help would be appreciated.
Function returned undefined, expected Promise or value
exports.compReqUpdated = functions.firestore
.document('/compRequests/{id}')
.onUpdate((change, contex)=>{
const newData = change.after.data();
//const oldData = change.before.data();
const dbConst = admin.firestore();
const reqStatus:string = newData.requestStatus;
const compId:string = newData.compID;
const reqActive:boolean = newData.requestActive;
if (reqStatus == "CANCELED" && reqActive){
const query = dbConst.collection('compRequests').where('compID', '==', compId);
const batch = dbConst.batch();
query.get().then(querySnapshot => {
const docs = querySnapshot.docs;
for (const doc of docs) {
console.log(`Document found at path: ${doc.ref.path}`);
console.log(doc.id);
const docRef = dbConst.collection('compID').doc(doc.id);
batch.update(docRef, {requestStatus: 'CANCELED',requestActive: false});
};
return batch.commit()
})
.catch(result => {console.log(result)});
}else{
return
}
});
The firebase docs state that the callback passed to the onUpdate function should return PromiseLike or any value, but you aren't returning anything right now. If you change your code to something as follows I reckon it should work as expected:
exports.compReqUpdated = functions.firestore
.document('/compRequests/{id}')
.onUpdate((change, contex) => {
const newData = change.after.data();
//const oldData = change.before.data();
const dbConst = admin.firestore();
const reqStatus: string = newData.requestStatus;
const compId: string = newData.compID;
const reqActive: boolean = newData.requestActive;
if (reqStatus == "CANCELED" && reqActive) {
const query = dbConst.collection('compRequests').where('compID', '==', compId);
const batch = dbConst.batch();
return query.get().then(querySnapshot => {
const docs = querySnapshot.docs;
for (const doc of docs) {
console.log(`Document found at path: ${doc.ref.path}`);
console.log(doc.id);
const docRef = dbConst.collection('compID').doc(doc.id);
batch.update(docRef, { requestStatus: 'CANCELED', requestActive: false });
};
return batch.commit()
}).catch(result => { console.log(result) });
} else {
return false;
}
});

Cypress: Cypress custom command's return value actually returns null in the test file

I created a Cypress custom command which displays the value using console.log (so I know it works). However, when I call the custom command in my Cypress test file, it returns blank / null.
support/commands.js:
Cypress.Commands.add('scanAWSDb', (siteId) => {
let siteName = null //default it to null
... some AWS SDK function which scans the DB and check for corresponding Name of the ID: 12345 ...
siteName = <new value>
console.log("Value returned is: " + siteName //This displays the value in the web console for the corresponding ID: 12345, let's say name is Taylor
return siteName //Expected to return "Taylor" in the test file
})
integration/test1.spec.js:
describe('Display value from the Custom command that scanned the AWS DB', ()=> {
it('Display value from the Custom command that scanned the AWS DB', () => {
const siteId = "12345"
cy.scanAWSDb(siteId)
.then((returned_value) => {
cy.log(returned_value) //This displays a null value so it is not picking up the return value from the custom command which is supposedly Taylor
})
})
})
===
Update:
This worked but when trying to do an assertion, it does not work as I am unable to convert an Object Promise to a string.
export const scanTable = async (tableName, recordId) => {
const params = {
TableName: tableName,
FilterExpression: '#Id = :RecordId',
ExpressionAttributeNames: {
'#Id': 'Id',
},
ExpressionAttributeValues: {
':RecordId': recordId
}
};
let scanResults = [];
let items
let index = 0
do{
items = await docClient.scan(params).promise()
items.Items.forEach((item) => scanResults.push(item))
params.ExclusiveStartKey = items.LastEvaluatedKey
let scannedRecordId = JSON.stringify(items.Items[index].Id)
cy.log('Record successfully found in table: ' + scannedRecordId )
index += 1
}while(typeof items.LastEvaluatedKey != "undefined")
return scannedRecordId;
};
Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
const record = scanTable(tableName, recordId)
cb(record) // Callback function
})
Test file:
const tableName = 'table1';
let recordId = '';
cy.scanDB(tableName, recordId, $returnValue => {
cy.log($returnValue) //<-- THIS DISPLAYS THE OBJECT BUT I NEED TO CONVERT IT TO STRING SO I CAN DO ASSERTION like this:
//expect($returnValue).to.eq(recordId)
})
===
Update#2: This displays the returned value but not picked up for assertion
aws.js file:
const AWS = require('aws-sdk')
const region = Cypress.env('aws_region')
const accessKeyId = Cypress.env('aws_access_key_id')
const secretAccessKey = Cypress.env('aws_secret_access_key')
const sessionToken = Cypress.env('aws_session_token')
let scannedRecordId = ''
AWS.config.update({region: region})
AWS.config.credentials = new AWS.Credentials(accessKeyId, secretAccessKey, sessionToken)
const docClient = new AWS.DynamoDB.DocumentClient();
export const scanTable = async (tableName, recordId) => {
const params = {
TableName: tableName,
FilterExpression: '#Id = :RecordId',
ExpressionAttributeNames: {
'#Id': 'RecordId',
},
ExpressionAttributeValues: {
':RecordId': recordId // Check if Id is stored in DB
}
};
let scanResults = [];
let items
let index = 0
do{
items = await docClient.scan(params).promise()
items.Items.forEach((item) => scanResults.push(item))
params.ExclusiveStartKey = items.LastEvaluatedKey
scannedRecordId = JSON.stringify(items.Items[index].Id)
cy.log('Record successfully found in table: ' + scannedRecordId)
index += 1 // This may not be required as the assumption is that only a unique record is found
}while(typeof items.LastEvaluatedKey != "undefined")
return scannedRecordId;
};
Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
const record = scanTable(tableName, recordId)
cb(record) // Callback function
// const record = scanTable(tableName, recordId).then(record => { cb(record) }) //This does not work and returns a console error
})
awsTest.js file:
const tableName = 'random-dynamodb-table'
let myId = '12345'
it('Verify if ID is stored in AWS DynamoDB', () => {
cy.scanDB(tableName, myId, $returnValue => {
cy.log($returnValue)
cy.log(`Record ID: ${myId} is found in table: ` + $returnValue)
expect($returnValue).to.deep.eq(myId) //This asserts that the Id is found
})
})
If this AWS function is async you should handle it like promise so instead:
let siteName = null //default it to null
... some AWS SDK function which scans the DB and check for corresponding Name of the ID: 12345 ...
siteName = <new value>
AWSFunction().then((newValue) => {
siteName = newValue
console.log("Value returned is: " + siteName)
return siteName
});
Also if in test you need to only read this value you can use callback instead of promise: e.g.
Cypress.Commands.add('scanAWSDb', (siteId, cb) => {
AWSFunction().then((newValue) => {
cb(newValue);
})
})
// test
cy.scanAWSDb(siteId, (returned_value) => {
cy.log(returned_value)
});
Updated:
To assert string from object you can use wrap and invoke cypress methods: docs
scan function is async, so you have to call it like this:
Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
const record = scanTable(tableName, recordId).then(record => { cb(record) };
})

On Deploying the Firebase Cloud Function getting an error of "Each then should return a value or throw"

I am new to Cloud Functions so I having issues with below code, the error is in the last part where the console.log is mentioned, please assist what shall I been done to deploy the Function successfully, as I am following a tutorial there is no such error for the name.
'use-strict'
const functions = require('firebase-functions');
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.sendNotifications = functions.firestore.document("users/{user_id}/notifications/{notification_id}").onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
return admin.firestore().collection("users").doc(user_id).collection("notifications").doc(notification_id).get().then(queryResult => {
const from_user_id = queryResult.data().from;
const message = queryResult.data().message;
const from_data = admin.firestore().collection("users").doc(from_user_id).get();
const to_data = admin.firestore().collection("user").doc(user_id).get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
title: "Notification from:" + from_name,
body: message,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(result =>{
console.log("notifcation sent");
});
});
});
});
By chaining your Promises and returning null in the last then(), as follows, you should solve your problem:
exports.sendNotifications = functions.firestore.document("users/{user_id}/notifications/{notification_id}").onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
return admin.firestore().collection("users").doc(user_id).collection("notifications").doc(notification_id).get()
.then(queryResult => {
const from_user_id = queryResult.data().from;
const message = queryResult.data().message;
const from_data = admin.firestore().collection("users").doc(from_user_id).get();
const to_data = admin.firestore().collection("user").doc(user_id).get();
return Promise.all([from_data, to_data]);
})
.then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
title: "Notification from:" + from_name,
body: message,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload)
})
.then(messagingResponse => {
console.log("notification sent");
return null; //Note the return null here, watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/
});
});
You may have a look at the corresponding MDN documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#Chaining
Also, note that, in your code, it seems that you are not using the to_name constant.

Categories

Resources