I'm using React Native with Expo, Jest for snapshot testing and Redux Toolkit with query. I want to create a snapshot but always getting an error TypeError. I think problem is in my mocks, I don't know how to mock an entire object of data. Example below:
jest.mock('../../services', () => ({
useGetOfficeDataQuery: jest.fn().mockReturnValue('Biuro księgowe')
}));
it('renders correctly', () => {
const snap = renderer.create(<ContactScreen />).toJSON();
expect(snap).toMatchSnapshot();
});
But in this mock I need to mock entire object like this below:
{
"id": "xxxxxxxxxxxxxxxxxxxxxxxx",
"name": "Xxxxxxxxxxxx",
"nip": "xxxxxxxxxx",
"phone": null,
"city": "xxxxx",
"zip_code": "xx-xxx",
"street": "xxxxxxxxxxxxxxxxx",
"house_number": "xxxxxxx",
"room_number": "xx",
"email": "xxxxxxxxx",
"email_correspondence": "xxxxxxxxxxxxxxx"
}
Okay I figured it out, to mock an object I needed to wrap this in { } and write it like a json, code example below:
jest.mock('../../services', () => ({
useGetOfficeDataQuery: jest.fn().mockReturnValue({
id: "xxxxxxxxxxxxxxxxxxxxx",
name: "xxxxxxxxxx",
}),
}));
Related
I cannot find a way to set serializableCheck to false only for specific slice.
const store = configureStore({
reducer: {
ApiSignalMenu: ApiSignalMenuSlice.reducer,
ApiSignalData: ApiSignalDataSlice.reducer,
ApiHistoricalMenu: ApiHistoricalMenuSlice.reducer,
ApiHistoricalYearData: ApiHistoricalYearDataSlice.reducer,
ApiUpProbabilityMenu: ApiUpProbabilityMenuSlice.reducer,
ApiUpProbabilityData: ApiUpProbabilityDataSlice.reducer,
ApiMoverData: ApiMoverDataSlice.reducer,
ApiChartingMenu: ApiChartingMenuSlice.reducer,
ApiChartingData: ApiChartingDataSlice.reducer,
ApiTicker: ApiTickerSlice.reducer
},
// middleware: (getDefaultMiddleware) =>
// getDefaultMiddleware({
// serializableCheck: false
// }
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: {
ignoredPaths: ['ApiMoverData.apiData.0'],
}
})
});
I have array data in : ApiMoverData
If I set : ignoredPaths: ['ApiMoverData.apiData.0'],
Then I got error again for A non-serializable value was detected in an action, in the path: payload.0. Value:, ApiMoverData
And
Then I got error again for Then I got error again for A non-serializable value was detected in the state, in the path: ApiMoverData.apiData.0
ApiMoverData.apiData.1, Then ApiMoverData.apiData.2, again.
How to set serializableCheck to false to all my array data in specific slice ?
This post : Is there a way to set the serializableCheck to false for one reducer only in redux?
did not tell a specific answer.
Thank You
EDIT :
My structure data looks like this :
Array [
ApiMoverData {
"change": "1,43",
"company": "Garuda Maintenance Facility Aero Asia Tbk.",
"id": 0,
"last": "71",
"ticker": "GMFI",
"value": "99.343.200",
"volume": "13.992",
},
ApiMoverData {
"change": "1,44",
"company": "Kimia Farma Tbk.",
"id": 1,
"last": "1.765",
"ticker": "KAEF",
"value": "956.208.000",
"volume": "5.433",
}
]
If I set : ignoredPaths: ['ApiMoverData.apiData']
Then I got error again for A non-serializable value was detected in an action, in the path: payload.0. Value:, ApiMoverData
And
Then I got error again for A non-serializable value was detected in the state, in the path: ApiMoverData.apiData.0
ApiMoverData.apiData.1, Then ApiMoverData.apiData.2, again.
Same Error
recomended by #phry do not use class instance in redux-toolkit. Because it will effect negative in future. Also we will not be able to use Redux-Persist. Just use non-class javascript object and store that.
I've deleted items from AdminUI in the 'Content' section, and I have deleted items also from 'items' in DynamoDB in AWS. The items do not appear on either 'Content' in AdminUI and not in the DynamoDB table, however when I query the following code, and then console.warn the array that comes back, I see the deleted items in react-native warn and I also see them in the Metro console but in the Metro console they have a value of "_deleted". How can I permanently get rid of the deleted items in the DB?
useEffect(() => {
const getCurrentUser = async () => {
const userId = await Auth.currentAuthenticatedUser();
const dbUsers = await DataStore.query(User, uzer =>
uzer.sub('eq', userId.attributes.sub),
);
console.warn(dbUsers);
};
getCurrentUser();
}, []);
This is what I see in the Metro console:
WARN [{"_deleted": undefined, "_lastChangedAt": undefined, "_version": undefined, "bio": "My bio", "gender": "", "id": "70cead42-6140-47ee-910b-ec0983cac170", "image": "https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/elon.png", "lookingFor": "FEMALE", "name": "Omerle", "sub": "68f43e08-42a1-46f8-a10e-39b92d80be88"}, {"_deleted": undefined, "_lastChangedAt": undefined, "_version": undefined, "bio": "This is my Bio", "gender": "", "id": "106fa724-5a9a-4be7-b369-3c4cfba18be0", "image": "https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/elon.png", "lookingFor": "FEMALE", "name": "Omer", "sub": "68f43e08-42a1-46f8-a10e-39b92d80be88"}]
When using DataStore, it first queries your data from the DynamoDB and then for all subsequent queries it retrieves the data from your device's local cache. Clearing the cache on your local device might solve your problem. More information here: https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/
How to update the cache, after creating new data?
Error message from Apollo
Store error: the application attempted to write an object with no provided id but the store already contains an id of UsersPermissionsUser:1 for this object. The selectionSet that was trying to be written is:
{
"kind": "Field",
"name": { "kind": "Name", "value": "user" },
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{ "kind": "Field", "name": { "kind": "Name", "value": "username" }, "arguments": [], "directives": [] },
{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }
]
}
}
Nativescript-vue Front-end Details
1- Watch Book Mobile app in action on YouTube: https://youtu.be/sBM-ErjXWuw
2- Watch Question video for details on YouTube: https://youtu.be/wqvrcBRQpZg
{N}-vue AddBook.vue file
apolloClient
.mutate({
// Query
mutation: mutations.CREATE_BOOK,
// Parameters
variables: {
name: this.book.name,
year: this.book.year,
},
// HOW TO UPDATE
update: (store, { data }) => {
console.log("data ::::>> ", data.createBook.book);
const bookQuery = {
query: queries.ALL_BOOKS,
};
// TypeScript detail: instead of creating an interface
// I used any type access books property without compile errors.
const bookData:any = store.readQuery(bookQuery);
console.log('bookData :>> ', bookData);
// I pin-pointed data objects
// Instead of push(createBook) I've pushed data.createBook.book
bookData.books.push(data.createBook.book);
store.writeQuery({ ...bookQuery, data: bookData })
},
})
.then((data) => {
// I can even see ID in Result
console.log("new data.data id ::::: :>> ", data.data.createBook.book.id);
this.$navigateTo(App);
})
.catch((error) => {
// Error
console.error(error);
});
What are these "Book:9": { lines in the cache?
console.log store turns out:
"Book:9": {
"id": "9",
"name": "Hadi",
"year": "255",
"__typename": "Book"
},
"$ROOT_MUTATION.createBook({\"input\":{\"data\":{\"name\":\"Hadi\",\"year\":\"255\"}}})": {
You can see all front-end GitHub repo here
Download Android apk file
Our goal is to update the cache. Add Book Method is in here:
https://github.com/kaanguru/mutate-question/blob/c199f8dcc8e80e83abdbcde4811770b766befcb5/nativescript-vue/app/components/AddBook.vue#L39
Back-end details
However, this is a frontend question a running Strapi GraphQL Server is here: https://polar-badlands-01357.herokuapp.com/admin/
GraphQL Playground
USER: admin
PASSWORD: passw123
You can see GraphQL documentation
I have so much simple Strapi GrapQL Scheme:
If you want to test it using postman or insomnia you can use;
POST GraphQL Query URL: https://polar-badlands-01357.herokuapp.com/graphql
Bearer Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTkwODI3MzE0LCJleHAiOjE1OTM0MTkzMTR9.WIK-f4dkwVAyIlP20v1PFoflpwGmRYgRrsQiRFgGdqg
NOTE: Don't get confused with $navigateTo() it's just a custom method of nativescript-vue.
It turns out;
all code was correct accept bookData.push(createBook);
// HOW TO UPDATE
update: (store, { data }) => {
console.log("data ::::>> ", data.createBook.book);
const bookQuery = {
query: queries.ALL_BOOKS,
};
// TypeScript detail: instead of creating an interface
// I used any type access books property without compile errors.
const bookData:any = store.readQuery(bookQuery);
console.log('bookData :>> ', bookData);
// I pin-pointed data objects
// Instead of push(createBook) I've pushed data.createBook.book
bookData.books.push(data.createBook.book);
store.writeQuery({ ...bookQuery, data: bookData })
},
})
Typescipt was helping
The point is; I shouldn't trust TypeScript errors, or at least I should read more about what it really says.
Typescript just asked me to be more specific while saying: Property 'push' does not exist on type 'unknown'
TypeScript was trying to tell me I need to be more specific while calling ROOT_MUTATION data. It said: Cannot find name 'createBook' But again I ignored it.
Solution Github Branch
https://github.com/kaanguru/mutate-question/tree/solution
Sources
how to update cache
Create interface for object Typescript
I am new in React-native and Redux, I am trying to do CRUD operation. How to update the state of store when we add data by api. I am calling Get Business Api in may action. and I store it into Store.
business action:
export const getBusinessByAliases = (aliases) => {
return (dispatch) => {
dispatch(getBusinessByAliasesData(aliases))
//API CALL
getBusiness(aliases)
.then(response=>{
//HERE I GET WHOLE BUSINESS DATA
dispatch(getBusinessByAliasesSuccess(response.data.business))
})
.catch(err => {
console.log("err",err)
dispatch(getBusinessByAliasesFailure(err))
})
}
}
business data is:
business:[
"id": "17bfdde3-bc04-4a9c-87e7-7530ded1b929",
"inserted_at": "2019-07-10T09:47:41",
"name": "Business2",
"employees": [
{
"nickname": "xyz",
"settings": null,
"user": {
"email": null,
"first_name": null,
"id": "582f5d07-146e-4a81-a6c0-7dd5208b43b2",
"image_id": null,
"inserted_at": "2019-07-02T13:41:06",
"last_name": null,
"phone": "+911234567890"
}
}
],
"services": [
{
"id": "34bd8c80-41e1-459a-bc09-d88a6894bd42",
"name": "Gsgsha",
"settings": {
"color": "#039BE5",
"duration": 4,
"price": 6
}
}
],
]
Now i am adding customer by calling create employee api in another action
employee action :
export const createNewEmployee = (businessName,data) => {
//console.log("whole data", data)
return (dispatch) => {
dispatch(createEmployee(businessName,data))
// API CALL
createEmployees(businessName,data)
.then(response=>{
//IN RESPONSE I GET SUCCESS MESSAGE WITH TRANSACTION ID
dispatch(createEmployeeSuccess(response.data.transaction_id))
})
.catch(err => {
console.log("errEmp",err)
dispatch(createEmployeeFailure(err))
})
}
}
Now, How do I update by the business state which contains all data with my new added employee entry?
I think the best solution is that your endpoint should response the new business object with all employes or only the new list of employes.
Keep in mind that your server can be modified by a lot of app clients, if you need to keep the information updated, you need to implement a Firebase protocol to update your store every time.
I get the result below from the url "https://api.myjson.com/bins/1f1pxv"
{
"categoria": "Graduação - Semipresenciais",
"cursos": [
{
"name": "Engenharia de Computação",
"tarefas": "1"
},
{
"name": "Engenharia de Computação",
"tarefas": "2"
},
{
"name": "Psicologia",
"tarefas": "4"
}
]
}
I use React Native and Axios to get the values
buscaCursosJson = () => {
axios.get("https://api.myjson.com/bins/1f1pxv").then(response => {
alert('x2: '+response.data.cursos.name)
alert('x1: '+response.data.categoria)
})
};
The alert 'x1' is showing correctly the result "Graduação - Semipresenciais", but the 'x2' alert is showing 'undefined' as a result.
How I can fix that?
I find how to fix the problem, I use the map function
response.data.cursos.map(data => alert(data.name))