Cypress.io: How to use Fixtures? - testing

I actually use the following code:
const userType = new Map([['Manager', '1'],['Developer', '2' ]])
for (const [key, value] of usertypes.entries())
{
it('log in', () =>
{
cy.login(key,value)
cy.xpath('path')
.click()
cy.xpath('path')
.should('have.value' , key)
})
}
To use the Users in other tests I want to define usertypes in a fixture named users. How can I use this fixture with this test?
My Json File looks like :
[[
{"key": "Manager"},
{"value": "1"}
],
[
{"key": "Developer"},
{"value": "2" }
]]
I tried to use cy.fixture in the beforeElse but I dont need this in every test and it was not right.
How can I use the data of users.json in my test?

Looking at your test, the test data is defined outside the it(), so cy.fixture() will not be possible to call outside a running test. In this case I will recommend you to use import, so:
Create a .js file(let's say in the fixtures folder) with your users
(don't forget Map allows keys of any type, so no object notation needed):
export const users = [
[
"Manager", 1
],
[
"Developer", 2
]
]
Import the variable and pass it as argument to your map constructor:
import { users } from '../fixtures/your_file.js';
const userCred = new Map(users);
for (const [name, password] of userCred.entries()) {
it('log in', () => {
cy.login(name, password)
})
}

Related

How to use a part of intercepted endpoint as a variable in my stub with Cypress

I am testing a frontend and I want to make my test more efficient
I have the following custom command:
cy.intercept('**/api/classification/dd86ac0a-ca23-413b-986c-535b6aad659c/items/**',
{ fixture: 'ItemsInEditor.json' }).as('ItemsInEditorStub')
This works correctly and is intercepts 25 times :). But the Id in the stub file has to be the same as in the requested Endpoint. Otherwise the frontEnd wilt not process it.
At this point I do not want to make 25 stubfiles in the fixture map.
In the printscreen you can see the different calls I need to intercept. The last ID I would like to save as variable and use it in the stub file
The Stub is like this:
{
"item": {
"version": 3,
"title": "Cars",
"rows": [],
"id": "dynamicIdBasedOnEndPoint" <- *Can we make it dynamic based on the ID in the endpoint*
},
"itemState": "Submitted"
}
UPDATE:
What I have for now is just the basic I guess:
cy.intercept('**/api/classification/*/items/**', {
body:
{
item: {
version: 3,
title: 'Cars',
rows: [],
id: '55eb5a28-24d8-4705-b465-8e1454f73ac8' //Still need this value to be dynamic and always the same as the intercepted '**'(wildcard)
},
itemState: "Submitted"
}
})
.as('ItemsInEditorStub')
cy.fixture('ItemsInEditor.json').then(ModFixture => {
cy.intercept('GET', '**/api/classification/**/items/id/**', (req) => {
const id = req.url.split('/').pop(); // last part of url path
ModFixture.item.id = id; // add the id dynamically
req.reply(ModFixture); // send altered fixture
})
}).as('ItemsInEditorStub')
Thanks to #Fody
You can make a dynamic fixture using javascript.
Ref Providing a stub response with req.reply()
cy.fixture('ItemsInEditor.json').then(fixture => {
cy.intercept('**/api/classification/dd86ac0a-ca23-413b-986c-535b6aad659c/items/**',
(req) => {
const id = req.url.split('/').pop(); // last part of url path
fixture.item.id = id; // add the id dynamically
req.reply(fixture); // send altered fixture
}
).as('ItemsInEditorStub')
})

what are the assertions that are used for check the order in below body in api tesing using cypress

This is the body for reorder. How can I do assertions to check the order for particular in array[3]
{
"dimName": "Women's Clothing",
"dimOrder": 2,
"dimType": "wa",
"dimId": "category#womens-clothing",
"dimParent": "category"
},
{
"dimName": "Jewelry 1",
"dimOrder": 1,
"dimType": "wa",
"dimId": "category#jewelry",
"dimParent": "category"
},
{
"dimName": "Handbags",
"dimOrder": 3,
"dimType": "wa",
"dimId": "category#handbags",
"dimParent": "category"
}
If you received the above as a json response in an API test, a couple of quick examples:
Check the order of id's like this
cy.request(...)
.then(response => {
expect(response[0].dimId).to.eq('category#womens-clothing')
expect(response[1].dimId).to.eq('category#jewelry')
expect(response[2].dimId).to.eq('category#handbags')
})
Check the dimOrder field is sequential like this
cy.request(...)
.then(response => {
const dimOrder = response.map(item => item.dimOrder)
expect(dimOrder).to.deep.eq([1,2,3]) // deep because is array matching
})
For easier assertions on a response, especially nested properties, you can use cy-spok. It's also quicker to comprehend.
const spok = require('cy-spok')
cy.request(...)
.its('response.body')
.should(spok({
propertieWithArray: [
{
// you can assert the properties equal exact values
dimName: "Women's Clothing",
dimOrder: 2,
dimType: "wa",
dimId: "category#womens-clothing",
dimParent: "category"
},
{
// you can assert properties meet specifications
dimName: spok.string, // Jewelry 1
dimOrder: spok.number, // 1
dimType: spok.type('string'), // wa
dimId: spok.startsWith('category'), // category#jewelry
dimParent: spok.endsWith('category') // category
},
{
// use combination
dimName: spok.string,
dimOrder: spok.gt(0),
dimType: "wa",
dimId: spok.test(/#/),
dimParent: "category"
}

Commitlint - Allow '/' in scope-enum

In my Angular project, I want to extend #commitlint/config-conventional with some pre-defined scopes.
The Angular project has a library for UI components (generated via ng generate library) and a default app which consumes the UI library.
In commitlint.config.js I've added the following lines:
module.exports = {
extends: ['#commitlint/config-conventional'],
rules: {
'scope-enum': [
2,
'always',
[
'ui-components',
'ui-components/badge',
'ui-components/button',
'ui-components/tooltip',
'core',
'account',
'plugins',
'settings',
'projects',
'shared',
'styles'
]
]
}
};
However, when I try to commit something with the scope: 'ui-components/tooltip':
fix(ui-components/tooltip): fix border
I get a commitlint error, saying that:
⧗ input: fix(ui-components/tooltip): fix border
✖ scope must be one of [ui-components, ui-components/badge, ui/button, ui-components/tooltip, core, account, plugins, settings, projects, shared, styles] [scope-enum]
✖ found 1 problems, 0 warnings
Unfortunately slashes aren't allowed in scopes.
To get around this I replace / with two dashes (--).
I wrote a script to grab subfolders and return an array:
https://gist.github.com/trevor-coleman/51f1730044e14081faaff098618aba36
[
'ui-components',
'ui-components--badge',
'ui-components--button',
'ui-components--tooltip',
...
]
According to source code, Commitlint use / for multiple scopes.
It means, you can commit like fix(core/account): fix border but you can't commit fix(ui-components/tooltip): fix border because you need to add tooltip in to your scopes first.
Here is source code: https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/rules/src/scope-enum.ts
Also, it is mentioned in here: https://github.com/conventional-changelog/commitlint/blob/master/docs/concepts-commit-conventions.md#multiple-scopes
You can write your own custom plugin to check scopes, I had the same issue, so I wrote one to solve this problem, see example commitlint.config.js below:
module.exports = {
extends: ["#commitlint/config-conventional"],
rules: {
"enhanced-scope-enum": [
2,
"always",
[
"ui-components",
"ui-components/badge",
"ui-components/button",
"ui-components/tooltip",
"core",
"account",
"plugins",
"settings",
"projects",
"shared",
"styles",
],
],
},
plugins: [
{
rules: {
"enhanced-scope-enum": (parsed, when = "always", value = []) => {
if (!parsed.scope) {
return [true, ""];
}
// only use comma sign as seperator
const scopeSegments = parsed.scope.split(",");
const check = (value, enums) => {
if (value === undefined) {
return false;
}
if (!Array.isArray(enums)) {
return false;
}
return enums.indexOf(value) > -1;
};
const negated = when === "never";
const result =
value.length === 0 ||
scopeSegments.every((scope) => check(scope, value));
return [
negated ? !result : result,
`scope must ${negated ? `not` : null} be one of [${value.join(
", "
)}]`,
];
},
},
},
],
}

React Native - Using promises when fetching and returning them to components

i want to display related data on react native, i have 2 response api
response 1
{
"total": 2,
"data" : [
{
"date" : "2020-12-01",
"time" : "08:00:00"
},
{
"date" : "2020-12-02",
"time" : "09:00:00"
}
]
}
response 2, date is parameter
date : 2020-12-01
{
"total": 2,
"data" : [
{
"date" : "2020-12-01",
"description" : "bla bla bla"
},
{
"date" : "2020-12-01",
"description" : "vla vla vla"
}
]
}
date : 2020-12-02
{
"total": 1,
"data" : [
{
"date" : "2020-12-02",
"description" : "cla cla cla"
}
]
}
how to use promises on fetch and how components return them,
so it can display content descriptions like this
Are you asking how to use promises with Fetch? Or how to take the results of those promises and use them to create a visual component?
It doesn't look like you've put any work into asking this question and it's quite wide ranging, from setting up components, creating fetch requests to an API and formatting them into visual components.
I'd consider starting here for your fetch request:
https://reactnative.dev/docs/network#making-requests
Then look at how they take the text and place it on a screen here:
https://reactnative.dev/docs/network#making-requests
EDIT:
Per the comments below.
You would most likely want to store the results of your request in some form of local state, and pass that state to your FlatList or similar, for instance:
const PromiseExample = () => {
const [listItems, setListItems] = useState([])
useEffect(() => {
async function fetchData() {
const data = await fetch('localhost:3000/data').json()
const otherData = await fetch('localhost:3000/otherData').json()
let joinedData = []
// at this point you would join your two data structures in whatever way you need to and push the joined data to the var.
setListItems(joinedData)
}
}, [])
return (
<FlatList data={listItems} />
)
}

Lodash: filter when I have nested array property?

Consider below example. I am using Lodash
"home":[
{
"data":{
"interests":["sports", "travel", "boxing"],
"city":["x", "y", "z"],
"name":"test1"
},
"count":["1", "2"],
"country":"CA"
},
{
"data":{
"interests":["painting", "travel", "dancing"],
"city":["a", "y", "b"],
"name":"test2"
},
"count":["1","3"],
"country":"US"
}
]
If I'll try the function on key value pair example :
_.find(home, ['data.country', 'US']); // It is returning me the 2nd object
requirement :
I want all the objects where data.interests is 'dancing'.
Tried :
_.find(home, ['data.interests', 'dancing']) // It is returning []
I have also tried filter(), where() and map but unable to get the complete object.
Thanks in advance.
You can use vanilla JS or lodash funcntions - Filter the array, and for each item check if the data.interests array includes the requested word.
Vanilla:
const home = [{"data":{"interests":["sports","travel","boxing"],"city":["x","y","z"],"name":"test1"},"count":["1","2"],"country":"CA"},{"data":{"interests":["painting","travel","dancing"],"city":["a","y","b"],"name":"test2"},"count":["1","3"],"country":"US"}]
const result = home.filter(o => o.data.interests.includes('dancing'))
console.log(result)
Lodash:
const home = [{"data":{"interests":["sports","travel","boxing"],"city":["x","y","z"],"name":"test1"},"count":["1","2"],"country":"CA"},{"data":{"interests":["painting","travel","dancing"],"city":["a","y","b"],"name":"test2"},"count":["1","3"],"country":"US"}]
const result = _.filter(home, o => _.includes(o.data.interests, 'dancing'))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>