How to search through JSON response with Cypress assertions - mocha.js

Considering the below API response I would like to assert the exact location of a certain value in a JSON structure. In my case the name of pikachu within forms:
"abilities": [
{
"ability": {
"name": "lightning-rod",
"url": "https://pokeapi.co/api/v2/ability/31/"
},
"is_hidden": true,
"slot": 3
},
{
"ability": {
"name": "static",
"url": "https://pokeapi.co/api/v2/ability/9/"
},
"is_hidden": false,
"slot": 1
}
],
"base_experience": 112,
"forms": [
{
"name": "pikachu",
"url": "https://pokeapi.co/api/v2/pokemon-form/25/"
}]
I would like to extend below code snippet to not scan the entire body as a whole as there are a lot of name's in the response, but rather go via forms to exactly pinpoint it:
describe('API Testing with Cypress', () => {
var baseURL = "https://pokeapi.co/api/v2/pokemon"
beforeEach(() => {
cy.request(baseURL+"/25").as('pikachu');
});
it('Validate the pokemon\'s name', () => {
cy.get('#pikachu')
.its('body')
.should('include', { name: 'pikachu' })
.should('not.include', { name: 'johndoe' });
});
Many thanks in advance!

Getting to 'forms' is just a matter of chaining another its(), but the 'include' selector seems to require an exact match on the object in the array.
So this works
it("Validate the pokemon's name", () => {
cy.get("#pikachu")
.its("body")
.its('forms')
.should('include', {
name: 'pikachu',
url: 'https://pokeapi.co/api/v2/pokemon-form/25/'
})
})
or if you just have the name,
it("Validate the pokemon's name", () => {
cy.get("#pikachu")
.its("body")
.its('forms')
.should(items => {
expect(items.map(i => i.name)).to.include('pikachu')
})
})
and you can assert the negative,
.should(items => {
expect(items.map(i => i.name)).to.not.include('johndoe')
})

Can you try the below code and see if it helps with your expectation. From the response you could get the name as below;
describe('API Testing with Cypress', () => {
var baseURL = "https://pokeapi.co/api/v2/pokemon"
beforeEach(() => {
cy.request(baseURL+"/25").as('pikachu');
});
it('Validate the pokemon\'s name', () => {
cy.get('#pikachu').then((response)=>{
const ability_name = response.body.name;
expect(ability_name).to.eq("pikachu");
})
});
})

Related

How tom send email using Mandrill in React.js App?

I am new to mandrill and am using mandrill to send emails in my React application. Also, I've registered my domain in mandril. I've read the documentation but I can't find it.
You can use this code as reference:
import { useEffect} from 'react'
const Checkout = () => {
useEffect(() => {
const requestOptions: RequestInit | undefined = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: 'YOUR_API_KEY',
message: {
text: 'Example text content',
subject: 'example subject',
from_email: 'example#gmail.com',
from_name: 'Example name',
to: [
{
email: 'example#target.com',
name: 'Example target name',
},
],
},
}),
}
fetch('https://mandrillapp.com/api/1.0/messages/send.json', requestOptions).then(
async (response) => {
const res = await response.json()
console.log(res)
}
)
}, [])
return (
<h1>Hello</h1>
)
}
export default Checkout

Cypress resets to cy.visit() after running each describe section

I have a spec file in Cypress below and every time it runs the spec, the "Analyze Section" succeeds but the "Other Section" fails due to it returning to the login page even though the before() hook at the root should just run once based on the level of nesting. I'm trying to make it so the login happens one time whenever any tests in this suite are run. Likewise, when any test in the "Analyze Section" are run we click the #HyperLinkAnalyze link one time to ensure we are on the proper page for any test. I was trying to make them cascade down but the beforeEach() call in each section ends up popping the page back out to the login page that happened in before().
context('Admin - Analyze Tab', { tags: ['#admin'] }, () => {
let user;
before(() => {
cy.visit(Cypress.env('admin_url'));
user = Cypress.env('admin_user');
cy.login(user.email, user.password);
});
describe('Analyze Section', ()=>{
beforeEach(() => {
cy.get('#HyperLinkAnalyze').click();
cy.get('#HyperLinkCampaignStats').click();
});
it('TEST 1', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
it('TEST 2', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
});
describe('Other Section', ()=>{
beforeEach(() => {
cy.get('#HyperLinkAnalyze').click();
cy.get('#HyperLinkXSellStats').click();
});
it('TEST 1', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
it('TEST 2', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
});
});
```js
You can try Cypress.session .
The new cy.session() command solves problem by caching and
restoring cookies, localStorage and sessionStorage after a successful
login. The steps that your login code takes to create the session will
only be performed once when it's called the first time in any given
spec file. Subsequent calls will restore the session from cache.
Set experimentalSessionSupport flag to true in the Cypress config or by using Cypress.config() at the top of a spec file.
Check below example -
const loginWithSession = () => {
cy.session(() => {
cy.visit(Cypress.env('admin_url'));
let user = Cypress.env('admin_user');
cy.login(user.email, user.password);// Can be parameterize
});
cy.visit(Cypress.env('admin_url'));//Or home page url
})
}
context('Admin - Analyze Tab', { tags: ['#admin'] }, () => {
before(() => {
loginWithSession();
});
describe('Analyze Section', ()=>{
beforeEach(() => {
loginWithSession();
cy.get('#HyperLinkAnalyze').click();
cy.get('#HyperLinkCampaignStats').click();
});
it('TEST 1', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
it('TEST 2', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
});
describe('Other Section', ()=>{
beforeEach(() => {
loginWithSession();
cy.get('#HyperLinkAnalyze').click();
cy.get('#HyperLinkXSellStats').click();
});
it('TEST 1', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
it('TEST 2', {}, () => {
cy.contains('#analytics-row1', 'Response Rate').should('be.visible');
});
});
});
In older version of Cypress you can use https://docs.cypress.io/api/cypress-api/cookies#Preserve-Once to preserve the cookies and Cypress will not clear it .
beforeEach(() => {
Cypress.Cookies.preserveOnce('session_id', 'remember_token')
})

store results from method in data form

I am going to preface this with I have NOT done this in a LONG time and my mind is mud. So no picking on me just remind me what I am doing wrong or not remembering.
NOTE: This is VueJS 3 / Tailwind 3 inside a Laravel 9 Jetstream Project
I have a method...
locatorButtonPressed() {
navigator.geolocation.getCurrentPosition(
position => {
console.log(position.coords.latitude);
console.log(position.coords.longitude);
},
error => {
console.log(error.message);
},
)
},
and I have a form data
data() {
return {
form: this.$inertia.form({
name: '',
email: '',
password: '',
password_confirmation: '',
birthdate: '',
user_latitude: '',
user_longitude: '',
user_city: '',
user_region: '',
user_country: '',
location: '',
terms: false,
})
}
}
I want to store position.coords.latitude and position.coords.longitude from the method in the form Data under user_latitude and user_longitude respectfully.
What am I forgetting???
The data properties can be accessed via this.PROPERTY_NAME. For example, to set form.user_latitude, use this.form.user_latitude = newValue.
export default {
methods: {
locatorButtonPressed() {
navigator.geolocation.getCurrentPosition(
position => {
this.form.user_latitude = position.coords.latitude;
this.form.user_longitude = position.coords.longitude;
})
},
}
}
demo

How to parse slug from url using route of laravel to vue components

I want to parse data to show product by using slug from laravel show route resource (get) to vue js components by using laravel api
example: https://shop.app/product/slug-name
i want to parse the slug-name into the vue components
export default {
name: 'product',
mounted() {
// console.log('Component mounted.')
this.fetchData()
},
data(){
return{
products: [],
product: {
id: '',
name: '',
slug: '',
description: '',
image: '',
created_at: '',
updated_at: ''
}
}
},
methods: {
fetchData(){
axios.get('/api/products')
.then((res) => {
this.products = res.data
})
.catch((err) => {
console.log(err)
})
}
}
}
i expect the output from showing the slug name, not show all the products
You can get you current url by
let currentUrl = window.location.pathname;
and then you can use lodash library its already included in laravel if you see you boostrap.js file
let ar = _.split(currentUrl, '/');
it will return your array. its just like explode in php. you can read about this here
and at last, get your product by
this.productName = _.last(ar);
`_.last` Its will just give you last element of your array which is your product. [here][2] is the documentation
you can make a method for this. like below
getProductSlug(){
let currentUrl = window.location.pathname;
let ar = _.split(currentUrl, '/');
return _.last(ar);
},
If you are using Laravel Routes you can get your slug in to your Vue instance like
var slugName = '{{ $slug }}';
export default {
name: 'product',
methods: {
fetchData(){
//you can use slugNname here
axios.get('/api/products/' + slugName)
.then((res) => {
this.products = res.data
})
.catch((err) => {
console.log(err)
})
}
}
after that you can use slugName in your axios request
hope it helps

Telegram bot keyboard

I create a telegram bot keaboard with laravel. There is a part of code.
$available_buttons =ReportToAbonent::select("report_id")
->join("telegram.reports", "report_to_abonent.report_id", "=", "reports.id")
->where("abonent_id", "=", $abonent[0]->id)
->where("active","=","1")
->get();
$keyboard = array();
foreach ($available_buttons as $value)
{
$keyboard[] = array($value->report_id);
}
$reply_markup = \Telegram::replyKeyboardMarkup([
'keyboard' => $keyboard,
'resize_keyboard' => true,
'one_time_keyboard' => false
]);
If I print
$keyboard`, its structure looks like if `$keyboard = [
['7', '8', '9'],
['4', '5', '6'],
['1', '2', '3'],
['0']
];
But in first case no keyboard in telegram client. In the second case it is present. What can I do wrong.
You have wrong format in inline keyboard, please check out API reference.
And you can refer to this sample request:
Contains only one button: (Parameters and Response)
Contains 2x3 buttons:
This is Two examples of each keyboard:
Normal Keboard:
const opts = {
reply_markup: JSON.stringify({
keyboard: [
['Normal'],
],
resize_keyboard: true,
one_time_keyboard: true,
}),
};
Inline Keboard:
const inlineopts = {
reply_markup: {
inline_keyboard: [
[{
text: 'Yahoo',
url: 'www.yahoo.com',
}],
[{
text: 'Google',
url: 'www.google.com',
}],
],
},
};

Resources