I wanted to check my navigations if it is dead / goes to the expected page,
i have a menu array, now i want to check if the link is not "#" then visit the url and should contain the those links,
so far i am stuck in this stage:
const menus = Menu;
context("Nav items test", () => {
beforeEach(() => {
cy.visit("/");
});
it("should redirect to the expected pages", () => {
cy.get(".navbar-nav>li>a[href!='/#']").each((links, index) => {
cy.wrap(links).click();
cy.url().should("contain", links[0].href);
});
});
export const Menu = [
{
id: 1,
title: "Home",
link: "/",
children: [],
},
{
id: 2,
title: "Consultants",
link: "#",
children: [
{ childTitle: "Find a Doctor", childTo: "/consultant/doctors" },
],
},
{
id: 3,
title: "Services",
link: "/services",
children: [
{
childTitle: "Clinical Laboratory",
childTo: "/services/laboratoryservices",
},
],
},
{
id: 4,
title: "Packages",
link: "/packages",
children: [],
},
];
cy.each() can pass three arguments into the callback - value (the currently yielded value), index (the position of the current value in the overall array), and collection (the entire array of yielded variables).
That being said, your current implementation wouldn't work either, as the DOM where you are getting your initial collection will become unattached when navigating to a new page. I would instead recommend doing two separate tests - one that validates that the href values are what you expect, and another that using cy.visit() to go to those href values does not redirect you.
it('validates the menu item href values are correct', () => {
cy.get(".navbar-nav>li>a[href!='/#']").each(($link, index) => {
cy.wrap($link).should('have.attr', 'href', menus[index].link);
});
});
it('validates navigating to each menu item does not redirect', () => {
menus.forEach((item) => {
cy.visit(item.link)
cy.url().should('eq', `${Cypress.config('baseUrl')}${item.link}`);
});
});
You may have to do some re-working, in case your app adds/removes trailing slashes, or other URL modifications.
Use cy.request() to test links with .each()
const results = []
cy.get(".navbar-nav>li>a[href!='/#']").each($a => {
const link = $a.prop('href')
cy.request({
url: link,
failOnStatusCode: false // allow good and bad responses
})
.then(response => {
results.push({link, ok: response.isOkStatusCode})
})
})
cy.then(() => {
console.log(results)
})
For example,
const results = []
cy.wrap(['http://example.com', 'http://not-valid.com']).each(link => {
cy.request({url: link, failOnStatusCode: false})
.then(result => {
results.push({link, ok: result.isOkStatusCode})
})
})
cy.then(() => {
console.log(results)
})
gives these results:
[
{link: 'http://example.com', ok: true}
{link: 'http://not-valid.com', ok: false}
]
Related
Since I've been experimenting with Nuxt3 and animation libraries, I came across an issue for which I need help finding a solution for.
I want to do an easy transition with some Javascript hooks no CSS/basic transitions.
When a page loads (onEnter), I want to reduce the height of a fixed black rectangle but for example sake, I'm just going to use the Nuxt example:
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'custom-flip',
mode: 'out-in',
onBeforeEnter: (el) => {
console.log('Before enter...')
},
onEnter: (el, done) => {},
onAfterEnter: (el) => {}
}
})
</script>
Everything working fine till you want to add an onBeforeLeave, onLeave or onAfterLeave hook.:
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'custom-flip',
mode: 'out-in',
onBeforeEnter: (el) => {
console.log('Before enter...')
},
onEnter: (el, done) => {},
onAfterEnter: (el) => {},
//nothings is logging underneath this
onBeforeLeave: (el) => {},
onLeave: (el, done) => {
console.log('this is not logging to the console...')
},
onAfterLeave: (el) => {}
}
})
</script>
Someone who experienced the same issue?
Trying to test two subdomains in integration.
However, localStorage is always set to first visited subdomain.
Is it possible to set localStorage value to the later visited subdomain (bar.company.com) in the example below?
describe('Login', () => {
it('Logins foo', () => {
cy.visit('https://foo.company.com');
localStorage.setItem('foo', 'foo');
});
it('Logins bar', () => {
cy.visit('https://bar.company.com');
// this will set the entry to foo.company.com
localStorage.setItem('bar', 'bar');
});
});
Now if we check localStorage at bar.company.com it is empty.
And foo.company.com has the both foo and bar entries.
You should either set testIsolation: true or call cy.clearAllLocalStorage() before all tests.
TestIsolation is designed to overcome this sort of issue, but you may not want it if there is some sort of continuity between tests (i.e data carries over).
Here is a reproducible example. There are two contexts, one with testIsolation on and one with it off.
Comment out the cy.clearAllLocalStorage() and you will see the tests start to fail.
Note that localstorage entries persist across runs in the Cypress UI.
context("localstorage - isolated", { testIsolation: true }, () => {
it("one", () => {
cy.visit("https://docs.cypress.io");
localStorage.setItem("one", "1");
cy.getAllLocalStorage().should("deep.eq", {
"https://docs.cypress.io": { one: "1" }
});
})
it("two", () => {
cy.visit('https://example.com/')
localStorage.setItem("two", "2");
cy.getAllLocalStorage().should("deep.eq", {
"https://example.com": { two: "2" }
});
})
})
context("localstorage - not isolated", { testIsolation: false }, () => {
before(() => {
cy.clearAllLocalStorage()
})
it("one", () => {
cy.visit('https://docs.cypress.io');
localStorage.setItem("one", "1");
cy.getAllLocalStorage().should("deep.eq", {
"https://docs.cypress.io": { one: "1" }
});
})
it("two", () => {
cy.visit('https://example.com')
localStorage.setItem("two", "2");
cy.getAllLocalStorage().should("deep.eq", {
"https://example.com": { two: "2" }
});
})
})
I have multiple links to test having the same test cases. I wanted to use fixture but it did not work. Can someone please help? I want to reiterate my tests for all links in the json file.
spec.js:
cy.readFile('cypress/fixtures/trial.json').then((details) => {
details.forEach((totest)=>{
cy.visit(totest.url)
})
})
fixture (.json):
"totest":[
{
"url": "https:www.link1.com"
},
{
"url": "https:www.link2.com"}
,
{
"url": "https:www.link3.com"
}
]
Your array is inside the totest property, so you need to add that
cy.fixture('trial.json').then((details) => {
details.totest.forEach((totest) => {
cy.visit(totest.url)
})
})
One test per URL
import details from './cypress/fixtures/trial.json'
//OR
const details = require('./cypress/fixtures/trial.json')
describe('tests URLs', () => {
details.totest.forEach(totest => {
it(`testing ${totest.url}`, () => {
cy.visit(totest.url)
})
})
})
I am trying to integrate my medium feed into gatsby and only want to select a few articles - not have the most recent ones. I was able to get the three most recent articles using this code:
index.config
mediumRssFeed:
"https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fmedium.com%2Ffeed%2F%40maxgraze",
shownArticles: 3,
Articles.js
const Articles = () => {
const MAX_ARTICLES = shownArticles
const { isIntroDone, darkMode } = useContext(Context).state
const [articles, setArticles] = useState()
const articlesControls = useAnimation()
// Load and display articles after the splashScreen sequence is done
useEffect(() => {
const loadArticles = async () => {
if (isIntroDone) {
await articlesControls.start({
opacity: 1,
y: 0,
transition: { delay: 1 },
})
fetch(mediumRssFeed, { headers: { Accept: "application/json" } })
.then(res => res.json())
// Feed also contains comments, therefore we filter for articles only
.then(data => data.items.filter(item => item.categories.length > 0))
.then(newArticles => newArticles.slice(0, MAX_ARTICLES))
.then(articles => setArticles(articles))
.catch(error => console.log(error))
}
}
loadArticles()
}, [isIntroDone, articlesControls, MAX_ARTICLES])
But I was hoping to query specific articles using gatsby-source-medium. However, it only returns 4 (and not even the most recent ones at that).
Is there a way to get all my articles via gatsby-source-medium? Otherwise, is there a way to "hard code" the articles I want? I'm not sure how to filter using the rss feed api. Thanks for yoru help!
As you suggested, there's a more native way using gatsby-source-medium but the documentation lacks good examples.
// In your gatsby-config.js
plugins: [
{
resolve: `gatsby-source-medium`,
options: {
username: `username/publication`,
},
},
]
Update:
It seems to be a known bug with Medium source and there's nothing we can do on our project. For further details:
gatsbyjs/gatsby#22491
A query like the following one will gather all posts from the user within the preview image:
query {
allMediumPost(sort: { fields: [createdAt], order: DESC }) {
edges {
node {
id
title
virtuals {
subtitle
previewImage {
imageId
}
}
author {
name
}
}
}
}
}
Learning VueJS and trying to do a simple API call on component load to put a list of repos onto my page. When I call and set the this.repos from the created() method, no problem. But if I set it as a method and then call it from this.getRepos nothing happens. No error, nothing. What am I missing about VueJS?
This works:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
},
async created() {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
This DOES NOT work:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
getRepos: async () => {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
},
created() {
this.getRepos();
},
Any ideas? Thanks!
It's simply because you used arrow functions here so that this.repos's this is bound to window object. Changing async () => {} to async function() {} will help you overcome it.
See demo
Note that you should not use an arrow function to define a method (e.g. plus: () => this.a++). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.a will be undefined.
reference
Another way to do an Axios call with Vue using then() method:
demo
created() {
axios.get('https://api.github.com/orgs/octokit/repos', {
params: {
type: 'all',
},
})
.then((res) => {
console.log('Success Response', res.data);
res.data.forEach((repo) => {
this.repos.push({ name: repo.name, url: repo.html_url, language: repo.language });
});
})
.catch((err) => {
console.log('Error', err);
});
},