cypress multiple commands writing on localstorage doesn't work properly - vue.js

My use case is when a user logs in he has to select a store to navigate.
So I wanted to create commands to reuse them.
commands.js
Cypress.Commands.add('login', () => {
localStorage.setItem('username', 'bob')
})
Cypress.Commands.add('selectStore', () => {
localStorage.setItem('storeId', 100001)
})
And my tests:
describe('Welcome', () => {
it('guest visits website, must login first', () => {
cy.visit('/')
cy.location('pathname').should('eq', '/login')
})
it('logged in user without store selected must select a store first', () => {
cy.login()
cy.visit('/')
cy.location('pathname').should('eq', '/stores')
})
it('logged in user with store selected should visit dashboard', () => {
cy.login()
cy.selectStore()
cy.visit('/')
cy.location('pathname').should('eq', '/dashboard')
})
})
This suite is passing first and second test but failing third.
The problem is:
cy.login() # localstorage has username key
cy.selectStore() # localstorage has storeId key but lost username key!
cy.visit('/')
cy.location('pathname').should('eq', '/dashboard') # cy.location('pathname') is '/login'
Why is happening this? Is this a bug? Is there something I'm doing wrong?
I tried agoff way but it does the same:
commands.js
Cypress.Commands.add('login', () => {
cy.window().then((window) => {
window.localStorage.setItem('username', 'bob')
})
})
Cypress.Commands.add('selectStore', () => {
cy.window().then((window) => {
window.localStorage.setItem('storeId', 100001)
})
})
Did you mean this?

Related

I keep getting Error: ResizeObserver loop limit exceeded in cypress

sorry I am new to cpyress
enter image description here
Cypress.on('uncaught:exception', (err, runnable) => {
return false;
}
I added this inside my code block
describe('TBoss Account Creation Credentials', () => {
Cypress.on('uncaught:exception', (err, runnable) => {
return false;
});
it('Identification Validation', () => {
cy.visit('our website')
cy.get('.mat-focus-indicator').click()
cy.wait(5000)
cy.origin('https://accounts.google.com/', () => {
cy.get('.Xb9hP').eq(0).type('1234')
cy.get('.VfPpkd-vQzf8d').eq(1).invoke('show').click()
cy.wait(5000)
cy.get('.whsOnd.zHQkBf').eq(0).type('1234', {force: true})
})
})
})
this is the code block, when I access to our website, it redirects me to google sign in page, I couldn't get() the google sign in input box for typing ID, so I used origin, and it works
however, after adding origin, it gives me that error.
on the google sign in page, I can successfully type the ID, and then it shows the password input form, thats where this error occurs
I want to get() the password input and type() the password and log in through google sign in form
please help me
The origin is sandboxed from the main page.
First thing to try is to move or copy the error catcher inside the cy.origion(). It may not work, there are some things that can't be run in there.
describe('TBoss Account Creation Credentials', () => {
it('Identification Validation', () => {
cy.visit('our website')
cy.get('.mat-focus-indicator').click()
cy.wait(5000)
cy.origin('https://accounts.google.com/', () => {
Cypress.on('uncaught:exception', (err, runnable) => {
return false;
});
cy.get('.Xb9hP').eq(0).type('1234')
cy.get('.VfPpkd-vQzf8d').eq(1).invoke('show').click()
cy.wait(5000)
cy.get('.whsOnd.zHQkBf').eq(0).type('1234', {force: true})
})
})
})

PWA fetch request in service worker sends "the site can't be reached" error on login with google the 2nd time

This error is really driving me crazy for the last 2 days. Please help.
So when I try to login with google the 1st time on my website, it doesn't cause any problem but when I try to do it the second time, with any account, it shows this error in the console:
The FetchEvent for "http://localhost:3000/auth/google/callback?code=4%2F0AX4somethingsomethingsomethingsomething&scope=profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile" resulted in a network error response: an object that was not a Response was passed to respondWith().
and the webpage shows this error:
This site can’t be reached The web page at http://localhost:3000/auth/google/callback?code=4%2F0AX4somethingsomethingsomethingsomething&scope=profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile might be temporarily down or it may have moved permanently to a new web address.
I am quite new to pwa and don't understand some of the code in the service worker file (I have copy pasted the 'fetch' part of the code from this webiste: blog.bitsrc.io) so that might be the reason I am not able to identify the error in the code. But you might identify it, this is my service worker code:
const staticCacheName = "site-static-v2";
const dynamicCacheName = "site-dynamic-v2";
const assets = ["/", "/stories", "/groups", "offline.html"];
// cache size limit function
const limitCacheSize = (name, size) => {
caches.open(name).then((cache) => {
cache.keys().then((keys) => {
if (keys.length > size) {
cache.delete(keys[0]).then(limitCacheSize(name, size));
}
});
});
};
// install event
self.addEventListener("install", (evt) => {
//console.log('service worker installed');
evt.waitUntil(
caches.open(staticCacheName).then((cache) => {
console.log("caching shell assets");
cache.addAll(assets);
})
);
});
// activate event
self.addEventListener("activate", (evt) => {
//console.log('service worker activated');
evt.waitUntil(
caches.keys().then((keys) => {
//console.log(keys);
return Promise.all(
keys
.filter((key) => key !== staticCacheName && key !== dynamicCacheName)
.map((key) => caches.delete(key))
);
})
);
});
// fetch events
self.addEventListener("fetch", function (event) {
event.respondWith(
fetch(event.request)
.catch(function () {
return caches.match(event.request);
})
.catch("offline.html")
);
});
This is my script in main.hbs (just like index.html).
if('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/serviceworker.js', { scope: '/' })
.then((reg) => console.log('Success: ', reg.scope))
.catch((err) => console.log('Failure: ', err));
})
}
I am making my website using express by the way.
I have tried pretty much every solution on stackoverflow but none seem to work.
Just for Information, I have also tried this for the 'fetch' part:
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cacheRes => {
return cacheRes || fetch(evt.request).then(fetchRes => {
return caches.open(dynamicCacheName).then(cache => {
cache.put(evt.request.url, fetchRes.clone());
// check cached items size
limitCacheSize(dynamicCacheName, 15);
return fetchRes;
})
});
}).catch(() => {
return caches.match('offline.html');
})
);
}
);
(The above code also lets me login only once but doesn't let me logout unlike the previous code)
I have copy pasted almost every 'fetch' code on the internet but all of them have a problem with google auth (I am using passport for google auth).
This is my auth.js code:
const express = require("express");
const router = express.Router();
const passport = require("passport");
//Authenticate with google
//GET /auth/google
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
//Google auth callback
//GET /auth/google/callback
router.get(
"/google/callback",
passport.authenticate("google", { failureRedirect: "/" }),
function (req, res) {
// Successful authentication, redirect home.
res.redirect("/stories");
}
);
router.get("/logout", (req, res) => {
req.logout();
res.redirect("/");
});
module.exports = router;
You can also suggest a workaround with workbox

Pass data from one API to another using Vue.js

I am making an API call to return a list of appointments. Each appointment has a clientID as a FK so that we can get client information. Is it possible to get that clientID when I make the call to the appointments API and use the clientID to make a call to a client using ID. Here is what I was thinking of how it might work but it is not working. Also an explanation of why this doesnt work would be nice.
export default{
data (){
return{
appointment: [],
client: []
}
},
created() {
axios.get("http://localhost:3000/api/appointment")
.then(res => this.appointment= res.data)
.catch(err => {
console.log(err)
}),
axios.get("http://localhost:3000/api/client/" + this.appointment.clientID)
.then(res => this.client = res.data)
.catch(err => {
console.log(err)
})
}
It does not work, beacause both axios calls are made simultanisously.
clientID is not defined, when you make the second axios call
Make sure the first call is done before using data from that response.
axios.get(...)
.then(response => {
this.appointment = response.data
axios.get(".../" + response.data.clientID)
.then(response => this.client = response.data
})
.catch(e => console.log(e))

How to integration test api endpoints of the format 'api/:id' using mocha and supertest

I am trying to integration test an API endpoint to return a specific user data by attaching the userId to the endpoint
I am currently able to test the endpoint that returns all users however when I try to write a test to return specific user data by attaching the user's id to the route I just end up testing the route returning all users.
describe('User profile route', () => {
let token = '';
let userId = '';
let userId1 = '';
useInTest();
it('should return a specific user details', (done) => {
signUp(mockData.signUpData).expect(201)
.end(() => {});
signUp(mockData.signUpData1).expect(201)
.end(() => {});
login(mockData.loginData)
.expect(200)
.end((err, res) => {
token = res.body.accessToken;
userId = res.body.user._id;
});
agent.get(`/api/users/${userId1}`).set('Authorization', 'Bearer ' + token)
.expect(200)
.end((err, res) => {
console.log(res.body);
res.body.should.have.length(1);
done();
})
});
}
I expect that test to pass but unfortunately, it doesn't simply it keeps hitting the this api/users instead of hitting this api/users/:id
I think this is not a supertest issue. How about you make test asynchronous because by the time your test makes a request the userId could be undefined since it is set after login. Try updating you code like this(add words in asterisks):
it('should return a specific user details', **async**(done) => {
signUp(mockData.signUpData).expect(201)
.end(() => {});
signUp(mockData.signUpData1).expect(201)
.end(() => {});
**await** login(mockData.loginData)
.expect(200)
.**then**((err, res) => {
token = res.body.accessToken;
userId = res.body.user._id;
});
agent.get(`/api/users/${userId1}`).set('Authorization', 'Bearer ' + token)
.expect(200)
.end((err, res) => {
console.log(res.body);
res.body.should.have.length(1);
done();
})
});
This is how I managed to get the issue solved completely
describe('User profile route', () => {
let token = '';
let userId = '';
let userId1 = '';
useInTest();
beforeEach( async () => {
signUp(mockData.signUpData).end(() => {});
signUp(mockData.signUpData1).end(() => {});
await login(mockData.loginData)
.then((res) => {
token = res.body.accessToken;
userId = res.body.user._id;
});
await login(mockData.loginData1)
.then((res) => {
userId1 = res.body.user._id;
});
});
it('should return user profile for the currently logged in user', (done) => {
agent.get('/api/users/' + userId).set('Authorization', 'Bearer ' + token)
.end((err, res) => {
res.body.should.have.property('name', 'Arnold');
done();
});
});
}

Detox - How to get a previous spec to run before a new spec runs to avoid duplicate test steps?

So I've wrote a test that logs in a user:
describe('Login', () => {
beforeEach(async () => {
await device.reloadReactNative()
})
it('Should grant access to a user with valid credentials', async () => {
test code
})
})
And now I'm writing a new spec to log out a user, so instead of writing the same test code again, I want the login spec to run within the log out spec. I would imagine it would look something like:
describe('Log Out', () => {
beforeEach(async () => {
await device.reloadReactNative()
it ('Should grant access to a user with valid credentials')
})
it('A User Logs Out', async () => {
test code
})
How do I get Detox to run the first login test before continuing with the new steps?
The beforeEach it ('Should grant access to a user with valid credentials') doesn't work unfortunately, so I'm missing something in the syntax.
This has no relation to Detox, this describe/it API is related to the test runner you are using. Anyway, use functions:
describe('Login', () => {
beforeEach(async () => {
await device.reloadReactNative();
await grantAccessToUserWithValidCredentials();
});
it('A User Logs Out', async () => {
// here the app is ready for you specific log out use case
});
async function grantAccessToUserWithValidCredentials() {
//grant it
}
});
Best practice is to use Drivers in your tests.
You can check out these slides:
http://slides.com/shlomitoussiacohen/testing-react-components#/7