Redux testing issue with Chai - testing

I'm learning react redux, I'm currently implementing some reducers using TDD. I'm working with a sample application, it's just a notepad for adding/removing/opening/closing notes.
I'm making some tests for adding a new note, but the second "it" is failing, the error that throws me is the following:
1) AddNote reducer should return two notes:
AssertionError: expected { Object (id-123, id-456) } to equal { Object (byId, ids, ...) }
describe('AddNote reducer' , () => {
it('should return a new note', () => {
const state = getMockState.withNoNotes();
const actualNextState = reducers.byId(
state.byId, actions.addNote(
'Hello World', 'id-123', 1));
const expectedNextState = {
'id-123': {
id: 'id-123',
content: 'Hello World',
timestamp: 1
}
};
expect(actualNextState).to.deep.equal(expectedNextState);
});
it('should return two notes', () => {
const state = getMockState.withOneNote();
const actualNextState = reducers.byId(state.byId, actions.addNote('Bye bye world!', 'id-456', 2));
const expectedNextState = {
...state,
'id-456': {
id: 'id-456',
content: 'Bye bye world!',
timestamp: 2
}
};
expect(actualNextState).to.deep.equal(expectedNextState);
});
});
I'm using also a helper, here it is
export const getMockState = {
withNoNotes: () => ({
byId: {},
ids: [],
openNoteId: null,
}),
withOneNote: () => ({
byId: {
'id-123': {
id: 'id-123',
content: 'Hello world',
timestamp: 1,
},
},
ids: ['id-123'],
openNoteId: 'id-123',
}),
};
The idea is if I add a note in the first case it would return a new state with just that note, but in the second case, it should return a state with the previous note, plus the new one.
I'm using Chai expect library with mocha.
If it helps here's the output of the state (it's a console log), which I think is ok,
{ 'id-123': { id: 'id-123', content: 'Hello World', timestamp: 1 } }
√ should return a new note
{ 'id-123': { id: 'id-123', content: 'Hello world', timestamp: 1 },
'id-456': { id: 'id-456', content: 'Bye bye world!', timestamp: 2 } }
1) should return two notes
Here's is my reducer
import { merge } from 'ramda';
export const byId = (state={}, {type, payload}) => {
switch(type) {
case 'app/addNote':
console.log(merge(state, { [payload.id]: payload})) ;
return merge(state, { [payload.id]: payload});
default:
return state;
}
};
Any ideas? thanks in advance!

Your expectedState is not correct. You are comparing the "next state" of byId slice, but your expectedNextState extends the whole state. It should actually be:
const expectedNextState = {
...state.byId,
'id-456': {
id: 'id-456',
content: 'Bye bye world!',
timestamp: 2
}
};

Related

Pass data from vue file to js file in vuejs?

In file : Product.vue
beforeCreate() {
const productId = this.$route.params.id;
axios
.get("/localhost/api/product/" + productId)
.then((res) => {
console.log(res.data); // result : {name: 'Iphone', status: 3, quantity: 100, price: 800}
})
.catch((error) => {
console.log(error);
});
},
I have a file productData.js on the same level as Product.vue. Now I want to transfer data of res.data through productData.js, how to do? In other words in productData.js I want to get the result of res.data when I call the API. Thanks.
update :
let data = null;
function initData(apiRes) {
data = apiRes;
console.log(data); // Output: "Hi from server"
// Do something with Data
}
console.log(data) // I want to get data outside the initData function
export { initData };
Simplest way is:
Product.vue
<script>
import { initData } from "./productData.js";
export default {
name: "Product",
props: {
msg: String,
},
data() {
return {
apiRes: "",
};
},
mounted() {
// your api call
this.apiRes = "Hi from server";
initData(this.apiRes);
},
};
</script>
productData.js
let data = null;
function initData(apiRes) {
data = apiRes;
console.log(data); // Output: "Hi from server"
// Do something with Data
doSomethingWithData();
}
function doSomethingWithData() {
// Your app logic that depends on data
// Here data will have value from API
}
// Here data is always null
export { initData };

Uncaught Error: Module parse failed: Shorthand property assignments are valid only in destructuring patterns

I get this error:
Uncaught Error: Module parse failed: Shorthand property assignments are valid only in destructuring patterns (74:14)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| dispatch('ADD_CHILDREN_TO_NODE', {
> doc = doc,
| })
| .finally(() => {
at eval (document-flow.module.js:1)
at Object../src/main/code/customers-self-data/vuex/modules/document-flow.module.js (_bundle.js?97212a2ac8be2d4b571f:8449)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (store.js:8)
at Module../src/main/code/customers-self-data/vuex/store.js (_bundle.js?97212a2ac8be2d4b571f:8473)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:3)
at Module../src/main/code/customers-self-data/index.js (_bundle.js?97212a2ac8be2d4b571f:8378)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:1)
This is my module:
import * as a from "../types/actions.types";
import * as g from "../types/getters.types";
import * as m from "../types/mutations.types";
import {
some imports
} from "#pn-js/core";
const documentFlow = {
namespaced: true,
state: {
documentFlowTree: null,
documentId: null,
childrens: null,
},
getters: {
[g.GET_DOCUMENT_FLOW_TREE](state) {
return state.documentFlowTree;
},
[g.GET_DOCUMENT_ID](state) {
return state.documentId;
},
[g.GET_CHILDRENS](state) {
return state.childrens;
},
},
mutations: {
[m.SET_DOCUMENT_FLOW_TREE](state, payload) {
state.documentFlowTree = payload;
},
[m.SET_DOCUMENT_ID](state, payload) {
state.documentId = payload.id;
},
[m.SET_CHILDRENS](state, payload) {
state.childrens = payload.childrens;
},
},
actions: {
[a.LOAD_DOCUMENT_FLOW_TREE]({ dispatch,commit, state }) {
var _documentTypeNamesMap = {
ORDER: order,
DELIVERY: delivery,
INVOICE: invoice,
};
let params = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.ID, state.documentId)
.build();
let res = [];
return Http.get({ params }).then((response) => {
//Compongo il nodo root
let firstNodeText =
_documentTypeNamesMap.ORDER + ":\t" + state.documentId;
let doc = [];
if (response.result) {
Object.keys(response.result).forEach((key) => {
doc.push(response.result[key].sequentDocuments.filter((d) => {
return d.docType.category === "DELIVERY";
}));
});
}
dispatch('ADD_CHILDREN_TO_NODE', { ====> This generates the error
doc = doc,
})
.finally(() => {
if (response.result) {
res.push({
text: firstNodeText,
state: { expanded: true },
children: state.childrens,
});
} else {
res = [
{
text: firstNodeText,
state: { expanded: true },
children: [{ text: noDataFound }],
},
];
}
commit(m.SET_DOCUMENT_FLOW_TREE, res);
});
});
},
[a.UPDATE_DOCUMENT_ID]({ commit }, payload) {
commit(m.SET_DOCUMENT_ID, payload);
},
[a.ADD_CHILDREN_TO_NODE]({commit},payload) {
let doc = payload.doc;
let childrens = [];
let matRegNodeText = "";
let i = 0;
Object.keys(doc).forEach((key) =>{
let docId = doc[key][0].docNum;
let deliveryParams = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.NUM, docId)
.build();
Http.get({
params: deliveryParams,
}).then((deliveryResponse) => {
if (deliveryResponse.result) {
matRegNodeText =
(doc[key][0].docType.category === "DELIVERY" ? goodsIssue : null) +
"\t\t\t" +
deliveryResponse.result.goodsReceiptNum +
"\t\t\t" +
deliveryResponse.result.actualMovDate;
}
let child = {
text: Strings.fsa.cdp.df.position + "\t" + response.result[i].docPos.posNum,
state: { expanded: true },
children: [{ text: matRegNodeText }],
};
childrens.push(child);
i++;
});
});
commit(m.SET_CHILDRENS,childrens);
}
},
};
export default documentFlow;
My question: is it possible to call an action from an action on the same module?
My problem is that before I didn't use the action to build the node (in the action loop my object doc to retrieve the data) but before being able to push the array childrens into property children of the object res, it was called asynchronous the commit, I thought about putting that piece of code inside a promise and then building the tree node but the result was the same.

useMutation not mutating the local state

I'm getting this error while trying to mutate the local state in apollo.
errInvariant Violation: Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a "gql" tag? http://docs.apollostack.com/apollo-client/core.html#gql
Initial state
registration: {
__typename: 'Registration',
tempMerchantId: '',
authorizeProfile: {
__typename: 'AuthorizePersonProfile',
nid_front: '',
nid_back: '',
authorized_person_photo: ''
}
}
My mutation
export const setAuthorizePersonQuery = gql`
mutation setAuthorizePersonProfileInfo($authorizePerosnData: Object!){
setAuthorizePersonProfileInfo(authorizePersonData: $authorizePerosnData) #client
}
`;
My resolver
export const setAuthorizePersonProfileInfo = (
_, { authorizePersonData }, { cache }
) => {
try {
const prevData = cache.readQuery({ getAuthorizePersonProfileQuery });
cache.writeQuery({
getAuthorizePersonProfileQuery,
data: {
registration: {
__typename: 'Registration',
authorizeProfile: {
__typename: 'AuthorizePersonProfile',
...prevData.registration.authorizeProfile,
...authorizePersonData
}
}
}
});
} catch (e) {
console.log(`err${e}`);
}
return null;
};
I'm trying to mutate the local state on button press, the function is
const handlePressedNext = () => {
Promise.all([
setAuthorizePersonProfileInfo({
variables: { authorizePersonData: generateNidData() }
})
])
.then(() => {
navigation.navigate('Photograph');
});
};
generateNidData function is like bellow
const generateNidData = () => ({
nid_front: nidFrontImage,
nid_back: nidBackImage
});
I'm new to apollo client. I can not understand what I'm doing wrong. Can anyone help me figure out the problem?
getAuthorizePersonProfileQuery is not a valid option for readQuery. Presumably, you meant use query instead.

How can I pass the value from my API to my head tittle with vue-head?

I am using vue-head in website because of I have to pass the name of the program to the html head, and the inf. it is coming from an API, so I make the request but every time I try to pass the name it send me error this the code:
export default {
data: () => ({
errors: [],
programs: [],
firstVideo: {},
vidProgram: {}
}),
},
created() {
//do something after creating vue instance
this.api = new ApiCanal({})
this.getProgram()
},
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.firstVideo = response.data[0]
this.vidProgram = response.data[0]['program']
})
.catch(error => {
this.errors = error
});
}
},
head: {
//this is the inf. for the head
title: {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
}
}
}
I will really appreciate if you can help me with this issue
If you want to use properties of your Vue object/component in the title there, you need to make it a function, as currently this refers to the object creating your Vue component (probably the global window object).
head: {
title: function() {
return {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
};
}
}

Realm "observer.next create #[native code]" exception

I am trying to fetch data with apollo and then write it to realm. I have created a js file that I know works, because it has worked before. But, when I try to write to a particular model I get an error message. More details as follows:
Code (Not entire code) LocationQuery.js:
const realm = new Realm({ schema: [testBuilding1], schemaVersion: 1 });
let buildingTypeArray = [];
const temp = [];
class LocationQuery extends Component {
static get propTypes() {
return {
data: React.PropTypes.shape({
loading: React.PropTypes.bool,
error: React.PropTypes.object,
sites: React.PropTypes.array,
}).isRequired,
};
}
render() {
if (this.props.data.loading) {
return (null);
}
if (this.props.data.error) {
return (<Text>An unexpected error occurred</Text>);
}
if (this.props.data.sites) {
this.props.data.sites.map((value) => {
buildingTypeArray.push(value.locations);
});
buildingTypeArray.forEach((locationValues) => {
realm.write(() => {
realm.create('testBuilding1', {
building: '273',
});
});
});
}
return null;
}
}
const locationQueryCall = gql`
query locationQueryCall($id: String!){
sites(id: $id){
locations {
building
type
}
}
}`;
const ViewWithData = graphql(locationQueryCall, {
options: props => ({
variables: {
id: 'SCH1',
},
}),
})(LocationQuery);
export default connect(mapStateToProp)(ViewWithData);
The error I get is a big red screen that read:
console.error: "Error in observe.next.... blah blah blah"
The Model I am using:
export const testBuilding1 = {
name: 'testBuilding1',
properties: {
building: 'string',
},
};
The weird thing is that the code works when I use this model:
export const locationScene = {
name: 'locationScene',
properties: {
building: 'string',
},
};
I am calling LocationQuery.js in another piece of code passing it through at render.
Thank you in advance for the help!