I am trying to automate my application with cypress. Have written few tests in my class and before visiting the site I have set up cookies (To login without entering username, password and otp). I have tried several ways to store these cookies and call before each of these tests but cookies work only for the 1st test and I am logged out for the subsequent tests.
Please find my code below. I am calling data using fixtures. It works fine only when i set sso and user agent for every test and I want to eliminate this.
describe('Watchlist Testsuite', () => {
let data;
before(() => {
cy.fixture('example').then((fdata) => {
data = fdata;
});
});
it('Setting up cookies', () => {
cy.setupCookies(data.sso, data.uid, data.userAgent, data.devId, data.url)
.then(() => cy.visit(data.url))
})
it('Enter Passcode', () => {
cy.setCookie('x-sso-token', data.sso)
cy.setCookie('x-user-agent', data.userAgent)
Cypress.config('pageLoadTimeout', 2000)
cy.enterPasscode(data.passcode)
Cypress.config('pageLoadTimeout', 20000)
cy.closeOKButton()
})
it('Create a watchlist', () => {
cy.setCookie('x-sso-token', data.sso)
cy.setCookie('x-user-agent', data.userAgent)
watchlistTest.createWatchlist(data.watchlistName)
})
Below are the ways with which I tried to preserve the cookies for all tests but none of them seem to be working.
Setting up cookies in beforeeach method
beforeEach('Setup cookies', ()=> {
cy.setupCookies(data.sso, data.uid, data.userAgent, data.devId, data.url)
.then(() => cy.visit(data.url))
})
Using cookies defaults
Cypress.Cookies.defaults
({
preserve:[data.sso, data.userAgent]
})
Using cy.session (I have set experimentalSessionAndOrigin to true)
it('setting up cookies',() => {
console.log('sso is ', data.sso)
const validate = () => {
cy.getCookie(data.sso).should('exist')
}
cy.session([window.sessionStorage.setItem('x-sso-token', data.sso),
window.sessionStorage.setItem('x-uid', data.uid),
window.sessionStorage.setItem('x-user-agent', data.userAgent),
window.sessionStorage.setItem('dev-id', data.devId)], {validate})
})
PS: I am using the Cypress 10.3.1 version.
Please guide me on the right approach to solve the issue.
Let's say we have the following suite:
describe('Devices', () => {
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
its('body.id')
.as('deviceId');
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.get('#deviceId').then((deviceId) => {
cy.sendData(deviceId, 'Some Data');
});
});
});
});
So, we have a set up suite that creates master data. This is a simplified version, actually it contains a couple of it specs and I'd like to keep it like that because it's better to read in the Cypress output.
Then, there is the actual test suite that want's to use data that has previously been created. In this case a server generated id that should be used for another REST call.
This is assuming, that cy.createDevice and cy.sendData are custom commands available that internally use cy.request.
When running that, cy.get('#deviceId') fails because aliases are not shared across describe blocks AFAIK. I tried to use let deviceId but it's undefined as it is not yet available when the test specs are processed.
What is a proper way to do this?
I believe this will be better solution, as cypress is asynchronous so it's better to write it on file and read it
describe('Devices', () => {
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
......
cy.writeFile('deviceId.txt', body.id)
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.readFile('deviceId.txt').then((device_id) => {
cy.sendData(device_id, 'Some Data');
})
});
});
});
Upvote for #ArekKhatry's idea, but to be safe I would obtain the the id in a before(). If you ever run tests in parallel, grabbing data from one test to use in another would be flaky.
Note that running cy.createDevice().its('body.id') in the before() still gives you the same test coverage as running inside it(), i.e it tests that the request succeeds and the return value has an id.
The file should be written to cypress/fixtures, otherwise it will write to the project root causing untidy pollution of the file structure.
Also, the id is returned from cy.request() as a number, but must be stringifyed in order to write to a text file.
Here's my variant
describe('Devices', () => {
before(() => {
cy.createDevice()
.its('body.id')
.then(id => {
cy.writeFile('cypress/fixtures/deviceId.txt', id.toString());
cy.log(`Created device: ${id}`);
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.fixture('deviceId') // can use simpler cy.fixture here
.then(device_id => { // returned as a string here
const id = parseInt(device_id); // may need to parse to number?
cy.sendData(id, 'Some Data');
})
});
});
});
Ok, so first thanks to Aloysius and Arek for their answers. But I had the gut feeling that there must be some easier way to do this that writing an Id to a file.
As I mentioned before, I had issues with my first attempt to use a global variable:
I tried to use let deviceId but it's undefined as it is not yet
available when the test specs are processed.
I really wanted to understand, why this did not work and did some console debugging.
I added a console log:
describe('Devices', () => {
console.log('Loading test suites...')
(...)
});
When running the tests, I saw the log output twice, once after the first describe block where the device id was stored and then a second time after the master data was written.
Actually, I found out that this issue was cause by the following known Cypress issue:
https://github.com/cypress-io/cypress/issues/2777
After setting the baseUrl, it actually works:
describe('Devices', () => {
let deviceId;
before( () => {
Cypress.config('baseUrl', Cypress.env('system_url'))
cy.visit('/');
})
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
.its('body.id')
.then((id) => {
deviceId = id;
});
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.sendData(deviceId, 'Some Data');
});
});
});
i hope y'all will be fine,
I am a beginner in webRTC sorry if my question feels like a noob one but i was wondering that is there any proper way to close the connection among peers especially using simple-peer.js, looking forward for your awesome replies
here is my sample react code,
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: { echoCancellation: true }, video: true }, stream => {
let peer = new Peer({
initiator: this.props.isInitiator,
stream
});
this.localStream.current.srcObject = stream;
this.localStream.current.play();
peer.on('signal', (data) => {
socket.emit('offer', { data: JSON.stringify(data), conversation_id: this.props.conversation_id })
});
socket.on('offer', (data) => {
peer.signal(JSON.parse(data))
})
socket.on('DESTROY-VIDEO-CALL-SESSION', () => {
stream.getTracks().forEach(track => track.stop());
peer.removeAllListeners();
peer.destroy();
});
peer.on('stream', (streamData) => {
this.remoteStream.current.srcObject = streamData;
this.remoteStream.current.play();
});
this.setState({
endCall: () => {
socket.emit('VIDEO-CALL-ENDED', this.props.conversation_id);
}
})
}, error => {
alert('Please allow video and audio permission to make this call')
});
}
The function is peer.destroy().
Fyi, if you need to find undocumented API functions in Javascript libraries, you can do this by running your JS file in the browser and pressing F12 to bring up the debugging console. Set a breakpoint after the object that you want to investigate is instantiated:
I set a breakpoint AFTER I instantiated peer1 (line 51). Then I hovered over peer1 (line 50) to pop up a menu of all of the properties (methods and fields) belonging to this object. If you're looking for a particular function as in this case, sometimes you find it immediately in this menu, but often you have to expand the property called __proto__ :
You can see the destroy function located here. It's just a guess whether or not a function found in this manner actually does what you want it to do, but luckily in this case it does what we want.
Issue
Within a React-Native (0.43) application we are using a component that uses a SectionList to render photos sorted by day. Each section can contain multiple images. Photos are taken using the react-native-image-crop-picker library and uploaded to the backend, or queued locally if no internet connection is available, encoded in base64 format. The image resolution is set to 800x800 pixels (requirement for other purposes of the images). On phones with lower memory, rendering ~20 images will crash the app due to insufficient memory. This issue can only be reproduced on low-end Android phones but I expect this to be a low memory issue and not related to the OS. To tackle this issue, thumbnails need to be generated to test if this is the case. Independent of when these thumbnails are generated (before sending to server or on-the-fly before loading component). The code below works fine for iOS but for Android it throws the error: Unknown protocol: data which comes from the ImageEditor.cropImage() function.
Snippet from main .js file
//The mergeReduxWithMeteor function takes care of merging the redux state,
//containing images not yet uploaded to the server,
//and the Meteor data as received by the server.
//No issues here...
helpers.mergeReduxWithMeteor(props.photoStore, props.SynergySummaryReady ? props.SynergyData : [])
//The imageHelper.compressPhoto does the actual compression
//No issues with the promise chain as is.
.then((data) => {
return Promise.all(data.map(imageHelper.compressPhoto))
})
// The remaining functions take care of the formatting for the SectionList.
// No issues here either... :)
.then((data) => {
return helpers.clusterDataByDay(data)
})
//We populate the resulting data in the state that is used for the SectionList
.then((data) => {
this.setState({NotHorusData: data})
})
.catch((error) => console.error(error))
imageHelper.compressphoto()
export function compressPhoto(photo) {
return new Promise((resolve, reject) => {
let imageSize = {
offset: {
x: 0,
y: 0
},
size: {
width: IMAGE_SIZE,
height: IMAGE_SIZE
},
displaySize: {
width: IMAGE_TARGET_SIZE,
height: IMAGE_TARGET_SIZE,
},
resizeMode: 'contain'
}
ImageEditor.cropImage(`data:image/jpeg;base64,${photo.data.userPhoto}`, imageSize, (imageURI) => {
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
resolve({
...photo,
data: {
...photo.data,
userPhoto: base64Data,
}
})
}, (error) => reject(error))
}, (error) => reject(error))
})
}
Approach 1: Fix data protocol issue on Android
Issue on Github from RN addresses the same issue but no solution is provided.
Approach 2: Bypass data protocol issue by providing uri on Android
Although less favourable due to the added communication/delay, another approach is to avoid the data protocol issue by providing a temporary URI provided by ImageStore. See the adapted code below for Android.
if(Platform.OS === 'android'){
ImageStore.addImageFromBase64(`data:image/jpeg;base64,${photo.data.userPhoto}`, (tempURI) => {
ImageEditor.cropImage(tempURI, imageSize, (imageURI) => {
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
ImageStore.removeImageForTag(tempURI)
resolve({
...photo,
data: {
...photo.data,
userPhoto: base64Data,
}
})
}, (error) => reject(error))
}, (error) => reject(error))
}, (error) => reject(error))
}
Unfortunately ImageStore.addImageFromBase64 is not recognised on Android.
Does anyone have any experience with ImageEditor and ImageStore on Android that might be helpful in this situation? Any other approaches are welcome too!
I managed to resolve the issue with the use of react-native-fetch-blob and react-native-image-resizer for both iOS and Android. Performance is unexpectedly good in comparison to the implementation in the question above. I shared the code below for others to use :)
export function compressPhoto(photo) {
return new Promise((resolve, reject) => {
let tempUri = `${cache}/Vire_${photo.data.userPhotoDate}.jpg`
fs.writeFile(tempUri, photo.data.userPhoto, "base64")
.then(() => {
ImageResizer.createResizedImage(
`file:${tempUri}`, IMAGE_TARGET_SIZE, IMAGE_TARGET_SIZE, "JPEG", 100, 0).then((resizedImageUri) => {
fs.readFile(`${resizedImageUri}`, "base64")
.then( data => {
resolve({...photo, data: { ...photo.data, userPhoto: data }})
})
.catch(error => reject(`readFile:error: ${error}`))
},
(error) => reject(`createResizedImage:error: ${error}`)
)
})
.catch( error => {
reject(`writeFile:error: ${error}`)
})
})
}
The gist is storing base64 encoded picture in the cache-directory and using imageResizer to fetch the image, compress it, and read it again in base64 for use.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm a beginner in Node (and generally all back-end web development), and I have started to write a RESTful API in Node. There are a few things I'm trying to get my head around.
My application uses Express and Mongoose, and I am using the express-resource module to easily create my CRUD routes for the API resources. But there are a couple of things I am unhappy about, and think I could do better.
The first is Mongoose. If I want to write tests for my API, I have no way of stubbing Mongoose to force it to in memory data. All of the tutorials out there seem to point to Mongoose, however, and I'm really not sure what I should be using.
Secondly, my resource seems to have a lot of boilerplate code. Is this really the best way to create a RESTful API in Node.js? Are there other modules that will help me to create my CRUD routes? I believe there are ways you can create CRUD routes right from your schema, without anymore code, but I'm really not sure how.
I have seen projects out there such as Tower.js and CompoundJS (formally RailwayJS) that seem to be these comprehensive solutions that solve much more than my issues here. Perhaps I should be using them, but I really only want the Node.js application to be an API and nothing more. I am dealing with the front-end independently of the API.
To provide some context, here is my current situation. Currently, I have a model defined in Mongoose:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
, Link
var LinkSchema = new Schema({
uri: String,
meta: {
title: String,
desc: String
},
shares: [{
uid: Schema.Types.ObjectId,
date: Date,
message: String
}]
})
Link = module.exports = mongoose.model('Link')
Next, I define the controllers for the CRUD routes:
var mongoose = require('mongoose')
, _ = require('underscore')
, Link = mongoose.model('Link')
exports.load = function (req, id, fn) {
Link.findById(req.params.link, function (err, link) {
if (err) {
return res.send(err)
}
fn(null, link)
})
}
exports.index = function (req, res) {
var filterByUser = req.query.user ? { 'shares.uid': req.query.user } : {}
Link.find(filterByUser, function (err, links) {
if (err) {
return res.send(err)
}
res.send(links)
})
}
exports.create = function (req, res) {
var link = new Link(req.body)
link.save(function (err) {
if (err) {
// TODO: send 404
return res.send(err)
}
res.send(link)
})
}
exports.show = function (req, res) {
res.send(req.link)
}
exports.update = function (req, res) {
req.link = _(req.link).extend(req.body)
req.link.save(function (err, link) {
if (err) {
return res.send(err)
}
res.send(link)
})
}
exports.patch = exports.update
exports.destroy = function (req, res) {
req.link.remove(function (err) {
if (err) {
return res.send(err)
}
res.send()
})
}
Finally, I use the express-resource module to map these controllers to the necessary CRUD routes on top of the Express app.
app.resource('api/links', require('../resources/links'))
You should look into restify
If you want to use express, you can also check out this project that I made -- called node-restful.
This library seems to be much more mature and have more features though: https://github.com/jspears/mers
Strongloop Loopback seeems to be another good alternative for generating Node/MongoDB APIs. It can also generate mocha tests too.
Take a look at Hapi its a configuration-centric framework for building web applications and APIs its used as restful service.
Other options are sails.js and actionhero
Strapi is a new (2015) framework.
The admin interface on their website allows you to create an API and specify relationships between models. (As can be seen in their introduction video.)
However it is designed to run on the Koa server, not on Express.
I recommend Baucis + Express. Thousands of users, model-driven design based on Mongoose, very flexible, spec-compliant, HATEOAS/Level 3 ready. Fits all my needs perfectly. But then, I'm the author :) https://github.com/wprl/baucis
Check this out:
With Feathers you can build prototypes in minutes and production ready real-time backends and REST APIs in days. Seriously.
Here is the issues about the frameworks nowadays.
When you come here from google searching "best", "fastest" framework blah, blah, people will drop a line says "Hey, you should try this sails.js, feathers, Derby etc..."
Ok The question is:
- Are you just for fun with those frameworks - if yes, you can easily get a list of frameworks and then start to benchmark them whatsoever.
I am assuming most of people are "I want to build a product, build a site can make money in the future, or at least it will become popular";
Ok, all you search keywords and attentions here is wrong, try to search "production ready", "enterprise ready", "case study" those keywords then, or maybe go to indeed.com and search node.js, further dig out what node.js framework most companies using, the answer maybe just simply say "express".
if so, From node.js stack, The frameworks will pretty much be narrowed down a few of them: Hapi, Strongloop, or even not popular one Mojito from Yahoo
For Those frameworks at least you can tell - "They are really production or enterprise ready" - cos' they have been using form Walmart, from Yahoo, from other big giants from some time, some even for couple of years.
Can this explain why Ruby on rails and Django still dominate the full stack framework markets? even you see lots of "cool" frameworks keeping on coming to the market, Meteor, Sails.js, Go's Revel, Java's Play Spark whatever you can name - It doesn't mean these frameworks worse than the two, just mean they need time to win the market.
Another problems lots of the current frameworks are a kind of all-in-one, clone of "Ror"; From the end user's prospect, They just need a thing to help them get things done, need productive, need something to work from the begin to the end, like Ruby on Rails, like MacOS, like windows, like anything itself which has been tested by the time, has been daily used by people.
I've been using Express to build my RESTful APIs on Node.js and with the addition of Router in Express 4, it's even easier to structure it. It's detailed here http://www.codekitchen.ca/guide-to-structuring-and-building-a-restful-api-using-express-4/
Try https://hivepod.io/ and generate your example in a full MEAN stack. Hivepod builds on top of BaucisJS + ExpressJS + MongoDB + AngularJS.
Disclaimer: I work building Hivepod.
Have a look into this link
This project is build using the same project archutecture which is followed by ASP.Net WebApi 2.0. That means it will be having controllers, authentication mechanism etc. to start with. All you need to do is create your own controllers.
I'm surprised no-one mentioned Nodal.
From the website:
Nodal is a web server for Node.js, optimized for building API services quickly and efficiently.
Boasting its own opinionated, explicit, idiomatic and highly-extensible framework, Nodal takes care of all of the hard decisions for you and your team. This allows you to focus on creating an effective product in a short timespan while minimizing technical debt
It's actively maintained, has 3800+ stars on Github (at the time of writing), has a command-line tool built-in to generate boilerplate code, and overall gets the job done quickly.
This is a sample to perform CRUD operations in a library system
var schema=require('../dbSchema');
var bookmodel=schema.model('book');
exports.getBooks = function (req,res) {
bookmodel.find().exec().then((data)=>{
res.send(data)
}).catch((err)=>{
console.log(err);
});
};
exports.getBook = function (req,res) {
var bkName=req.params.Author;
bookmodel.find({Name:bkName}).exec().then((data)=>{
res.send(data)
}).catch((err)=>{
console.log(err);
});
};
exports.getAutBooks = function (req,res) {
bookmodel.find({},'Author').then((data)=>{
res.send(data);
}).catch((err)=>{
console.log(err);
});
};
exports.deleteBooks=function(req,res){
var bkName=req.params.name;
bookmodel.remove({Name:bkName}).exec().then((data)=>{
res.status(200);
console.log(bkName);
}).catch((err)=>{
console.log(err);
});
};
exports.addBooks=function(req,res){
var newBook=new bookmodel({
Name:req.body.Name,
ISBN:req.body.ISBN,
Author:req.body.Author,
Price:req.body.Price,
Year:req.body.Year,
Publisher:req.body.Publisher
});
newBook.save().then(()=>{
res.status(201);
}).catch((err)=>{
console.log(err);
});
};
I am a big fan of express and I've been using it to build RESTful APIs on Node.js which are easier to build. However, when our application started growing, we ended in a situation where express structure did not scale well and with more code splitting around, it was harder for us to maintain.
I am from C#/Java background where SOLID principles are heavily used. Frameworks like Java Spring / C# WebAPI are proven to create enterprise level applications.
I wanted to have a framework where I can reuse my existing C#/Java skills (reuse I mean MVC architecture, OOPS, SOLID, DI, Mocks ... yeah, strong typing). Unfortunately, I did not find a framework which meets my requirements (It should have less learning curve, minimalist codebase size, completely express compatible).
What do I mean by completely express compatible? Whatever express does, I must be able to do it even If I use a framework on top of it, when I have looked into Strongloop Loopback it was pretty good to use but It had a lot of documentation to go through and the frameworks are coupled, not really what I was looking for.
So I have created Dinoloop powered by Typescript (has interfaces, classes, abstract classes and strong oops). The package is pretty stable now.
With Dinoloop you can build enterprise level applications in a scalable architecture.
It uses Dependency Injection framework but you can configure any DI frameworks available in typescript. Dinoloop enables typescript to use as a Nodejs REST framework that helped me to maintain common typescript codebase for both angular and node projects.
So, Dinoloop is a perfect fit for typescript lovers and angular developers.
var mongoose = require('../DBSchema/SchemaMapper');
var UserSchema = mongoose.model('User');
var UserController = function(){
this.insert = (data) => {
return new Promise((resolve, reject) => {
var user = new UserSchema({
userName: data.userName,
password: data.password
});
user.save().then(() => {
resolve({status: 200, message: "Added new user"});
}).catch(err => {
reject({status: 500, message: "Error:- "+err});
})
})
}
this.update = (id, data) => {
return new Promise((resolve, reject) => {
UserSchema.update({_id: id}, data).then(() => {
resolve({status: 200, message: "update user"});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.searchAll = () => {
return new Promise((resolve, reject) => {
UserSchema.find().exec().then((data) => {
resolve({status: 200, data: data});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.search = (id) => {
return new Promise((resolve, reject) => {
UserSchema.find({_id:id}).exec().then(user => {
resolve({status: 200, data: user});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.delete = (id) => {
return new Promise((resolve, reject) => {
UserSchema.remove({_id:id}).then(() => {
resolve({status: 200, message: "remove user"});
}).catch(err => {
reject({status: 500, message:"Error:- " + err});
})
})
}
}
module.exports = new UserController();
///Route
var express = require('express');
var router = express.Router();
var Controller = require('./User.Controller');
router.post('/', (req, res) => {
Controller.insert(req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.put('/:id', (req, res) => {
Controller.update(req.params.id, req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.get('/', (req, res) => {
Controller.searchAll().then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.get('/:id', (req, res) => {
Controller.search(req.params.id).then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.delete('/:id', (req, res) => {
Controller.delete(req.params.id).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
})
module.exports = router;
//db`enter code here`schema
var mongoose = require('mongoose');
const Schema = mongoose.Schema;
var Supplier =new Schema({
itemId:{
type:String,
required:true
},
brand:{
type:String,
required:true
},
pno:{
type:String,
required:true
},
email:{
type:String,
required:true
}
});
mongoose.model('Inventory',Inventory);
mongoose.model('Supplier',Supplier);
mongoose.connect('mongodb://127.0.0.1:27017/LAB', function (err) {
if (err) {
console.log(err);
process.exit(-1);
}
console.log("Connected to the db");
});
module.exports = mongoose;