how to do this in array? How to get the index per log?
code :
cy.fixture('weekly_report0.json').then((data) => {
cy.addContext('Total Calls:')
for (var index in data) {
cy.log(data[index].__EMPTY_1)
}
})
enter image description here
I wanted to get the index of the log which is equal to "Summary"
I guess you are working with a json file.
So, let me show this test first, which runs perfectly:
it('just testing', () => {
var jsonVar = {
name: "pepe",
lastName: "ruiz",
salary: 1234
}
var arrayData = Object.values(jsonVar)
arrayData.forEach((val, index)=>{
cy.log(`index: ${index} and value ${val}`)
})
});
Now, I will try to adapt it in this way:
cy.fixture('weekly_report0.json').then((data) => {
cy.addContext('Total Calls:')
var arrayData = Object.values(data)
arrayData.forEach((val, index)=>{
cy.log(`index: ${index} and value ${val}`)
})
})
Related
My data model is a list with items. Very simple:
{
_id: 1,
name: "List 1",
items: [
{ _id: 2, text: "Item text 1" },
{ _id: 3, text: "Item text 2" }
]
}
Adding a new list with optimistic response works perfectly:
const [addListMutation] = useAddListMutation({
update: (cache, { data }) => {
const cachedLists =
(cache.readQuery<GetAllListsQuery>({
query: GetAllListsDocument,
})?.lists as TList[]) ?? [];
if (data) {
cache.writeQuery({
query: GetAllListsDocument,
data: {
lists: [...cachedLists, data?.list as TList],
},
});
}
},
});
const addList = async (name: string) => {
const list = {
_id: ..new id here,
name,
items: [],
};
const variables: AddListMutationVariables = {
data: list,
};
await addListMutation({
variables,
optimisticResponse: {
list,
},
});
};
This gets reflected immediately in my component using const { loading, data } = useGetAllListsQuery();. data is updated twice; first with the optimistic response and then after the mutation is done. Just like expected.
Now I'm trying to add an item to the list this way:
const [updateListMutation] = useUpdateListMutation({
update: (cache, { data }) => {
const cachedLists =
(cache.readQuery<GetAllListsQuery>(
{
query: GetAllListsDocument,
},
)?.lists as TList[]) ?? [];
if (data?.list) {
// Find existing list to update
const updatedList = data?.list as TList;
const updatedListIndex = cachedLists.findIndex(
(list: TList) => list._id === updatedList._id,
);
// Create a copy of cached lists and replace entire list
// with new list from { data }.
const updatedLists = [...cachedLists];
updatedLists[updatedListIndex] = { ...updatedList };
cache.writeQuery({
query: GetAllListsDocument,
data: {
lists: updatedLists,
},
});
}
}
});
const updateList = async (updatedList: TList) => {
const variables: UpdateListMutationVariables = {
query: {
_id: updatedList._id,
},
set: updatedList,
};
await updateListMutation({
variables,
optimisticResponse: {
list: updatedList,
},
});
};
const addListItem = async (list: TList, text: string) => {
const updatedList = R.clone(list);
updatedList.items.push({
_id: ...new item id here,
text: 'My new list item',
});
await updateList(updatedList);
};
The problem is is in my component and the const { loading, data } = useGetAllListsQuery(); not returning what I expect. When data first changes with the optimistic response it contains an empty list item:
{
_id: 1,
name: "List 1",
items: [{}]
}
And only after the mutation response returns, it populates the items array with the item with text 'My new list item'. So my component first updates when the mutation is finished and not with the optimistic response because it can't figure out to update the array. Don't know why?
(and I have checked that the updatedLists array in writeQuery correctly contains the new item with text 'My new list item' so I'm trying to write the correct data).
Please let me know if you have any hints or solutions.
I've tried playing around with the cache (right now it's just initialized default like new InMemoryCache({})). I can see the cache is normalized with a bunch of List:1, List:2, ... and ListItem:3, ListItem:4, ...
Tried to disable normalization so I only have List:{id} entries. Didn't help. Also tried to add __typename: 'ListItem' to item added, but that only caused the { data } in the update: ... for the optimistic response to be undefined. I have used hours on this now. It should be a fairly simple and common use case what I'm trying to do :).
package.json
"#apollo/client": "^3.3.4",
"graphql": "^15.4.0",
"#graphql-codegen/typescript": "^1.19.0",
I have a web part that which needs to retrieve the Name property of a person column (a people picker) so I can populate state with it and subsequently populate a field. Here's the function that queries the item:
private _jeChange = (ev: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number) => {
this.setState({
SelectedJE: option.text,
}, () => {
const selJE = this.state.SelectedJE;
if (selJE && selJE.length > 0) {
let _item = this.state.MyListItems.find((item) => {
return item.JobRef == selJE;
});
this.setState({
JEDeptContact: _item.DeptContactId,
}, () => {
sp.web.lists.getByTitle("MyList").items.getById(_item.Id).select("DeptContact", "Lookup/Name", "Lookup/ID").expand("Lookup").get().then((item: any[]) => {
console.log(item);
});
});
}
});
}
The _item.DeptContactId successfully populates the state with the Id of the user in the person column, but I want the Name not the Id, how would I resolve the Id to the Name? Do I need to use expand to get the Name? If so how?
I've read this but I don't know where to use the expand:
https://pnp.github.io/pnpjs/sp/items/
Found it:
if(_item.DeptContactId){
sp.web.getUserById(_item.DeptContactId).select("Title", "DeptContact/Title").expand("DeptContact").get().then(r => {
this.setState({
JEDeptContact: r.Title,
});
});
\Created a Cypress Testscript in and set for execution in loop as would like to execute with multiple set of testdata in fixture json.if you down and see the cy.fixture is works only for first entry and test executed twice with fisrt entry in json (testdata file ) .anyhelp on how to include Iteration of array along with fixture would be helpful
var Launchindex = 0;
for (Launchindex = 0; Launchindex < 2; Launchindex ++) {
describe('Launch testsite',() => {
it('try login using testdata', () => {
cy.visit('https://xyzz')
cy.title().should('contain','title check')
})
it('check url', () => {
cy.url().should('contain','xyz')
})
it('enter details and submit', () => {
//Fixture loads the testdata setup in fixtures folder , so setup testdata required before executing test script
cy.fixture('testdata').then(testdata => {
const ModuleID = testdata[0].ModuleID
const LoginName = testdata[0].LoginName
const gameid = testdata[0].gameid
cy.get('#ModuleID').type(ModuleID)
cy.get('#LoginName').type(LoginName)
cy.get('#gameid').type(gameid)
cy.get('#btnSubmit').click()
})
})
})
}
fixture file looks somethings like this
[
{"id": 0,"ModuleID": "xxxx","LoginName": "xxxx","gameid": "xxxx"},
{"id": 1,"ModuleID": "yyy","LoginName": "yyy","gameid": "yyyy"}
]
cy.fixture('testdata') will be evaluated when Cypress executes it, so a loop in the top level of a module won't work.
You can do this instead:
describe('Launch testsite', () => {
it('enter details and submit', () => {
cy.fixture('testdata').then(testdata => {
testdata.forEach(data => {
const ModuleID = data.ModuleID;
const LoginName = data.LoginName;
const gameid = data.gameid;
cy.get('#ModuleID').type(ModuleID);
cy.get('#LoginName').type(LoginName);
cy.get('#gameid').type(gameid);
cy.get('#btnSubmit').click();
// in a real test you probably need to do some kind of assertion here
});
});
});
});
I tried reactive form valueChanges but valueChanges method doesn't return input field name which has changed.
I thought code like this. but I think this is not smart way. Because I have to compare every each input field. so I need more smart way.
// get init view data from local storage
this.localstorageService.getPlaceDetail().subscribe(data => {
this.initPlaceDetail = data;
// watch changed value
this.editPlaceForm.valueChanges.subscribe(chengedVal => {
if (chengedVal['ja_name'] !== this.initPlaceDetail.languages.ja.name.text) {
this.changedJA = true;
}
if (chengedVal['ja_romaji'] !== this.initPlaceDetail.languages.ja.name.romaji) {
this.changedJA = true;
}
// ...... I have to check all input fields??
});
});
I'm adding form controls from an array and something like this worked for me. Just reference the item you need instead of expecting the valueChanges observable to pass it to you.
myFields.forEach(item => {
const field = new FormControl("");
field.setValue(item.value);
field.valueChanges.subscribe(v => {
console.log(item.name + " is now " + v);
});
});
This is my way to get changed control in form.
I shared for whom concerned.
Method to get list control changed values
private getChangedProperties(form): any[] {
let changedProperties = [];
Object.keys(form.controls).forEach((name) => {
let currentControl = form.controls[name];
if (currentControl.dirty)
changedProperties.push({ name: name, value: currentControl.value });
});
return changedProperties;
}
If you only want to get latest changed control you can use
var changedProps = this.getChangedProperties(this.ngForm.form);
var latestChanged = changedProps.reduce((acc, item) => {
if (this.changedProps.find(c => c.name == item.name && c.value == item.value) == undefined) {
acc.push(item);
}
return acc;
}, []);
Instead of listening to whole form changes you can listen to value changes event for each form control as shown in below code:
this.myForm.get('ja_name').valueChanges.subscribe(val => {
this.formattedMessage = `My name is ${val}.`;
});
I try to retrieve datas in a subcollection based on the key received on the first call.
Basically, I want a list of all my user with the total of one subcollection for each of them.
I'm able to retrieve the data from the first Payload, but not from pointRef below
What is the correct way to achieve that?
getCurrentLeaderboard() {
return this.afs.collection('users').snapshotChanges().map(actions => {
return actions.map(a => {
const data = a.payload.doc.data()
const id = a.payload.doc.id;
const pointRef: Observable<any> = this.afs.collection('users').doc(`${id}`).collection('game').valueChanges()
const points = pointRef.map(arr => {
const sumPoint = arr.map(v => v.value)
return sumPoint.length ? sumPoint.reduce((total, val) => total + val) : ''
})
return { id, first_name: data.first_name, point:points };
})
})
}
I tried to put my code in a comment, but I think it's better formated as a answer.
First you need subscribe your pointRef and you can change your code like this.
getCurrentLeaderboard() {
return this.afs.collection('users').snapshotChanges().map(actions => {
return actions.map(a => {
const data = a.payload.doc.data()
const id = a.payload.doc.id;
const pointRef: Observable<any> = this.afs.object(`users/${id}/game`).valueChanges() // <--- Here
const pointsObserver = pointRef.subscribe(points => { //<--- And Here
return { id, first_name: data.first_name, point:points };
})
})
}
....
//Usage:
getCurrentLeaderboard.subscribe(points => this.points = points);
And if you going to use this function alot, you should start to denormalize your data.