relatively new to testing framework, facing below issue where I'm running 'npm run test' on a newly created spec.ts file with no extra test cases added
I'm facing issue that the map function used upon #input element is undefined
spec.ts
beforeEach(() => {
fixture = TestBed.createComponent(InputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.ngOnInit();
});
it('should create', () => {
expect(component).toBeTruthy();
});
InputComponent.ts
#Input() set column(colData: Columns[]) {
this.columns = colData;
}
ngOnInit(){
this.colName = this.columns.map(col => col.name);
}
TypeError: Cannot read property 'map' of undefined
You just need to input initial value of the variable and make sure it's array. because map is a property of array.
InputComponent.ts
columns = []; <-- initial value;
#Input() set column(colData: Columns[]) {
this.columns = colData;
}
ngOnInit(){
this.colName = this.columns.map(col => col.name); <-- You haven't declared the initial value of the "this.columns"
}
Related
I try execute on my view-post.component.ts
with treeview
Here is my code
constructor(private postService: PostService, private activateRoute: ActivatedRoute,
private commentService: CommentService, private router: Router) {
this.postId = this.activateRoute.snapshot.params.id;
this.commentForm = new FormGroup({
text: new FormControl('', Validators.required)
});
this.commentPayload = {
text: '',
postId: this.postId
};
this.dataSource.data = this.comments;
}
private _transformer = (node: CommentPayload, level: number) => {
return {
expandable: !!node.dtoList && node.dtoList.length > 0,
username: node.username,
text: node.text,
level: level,
};
};
treeControl = new FlatTreeControl<ExampleFlatNode>(
(node) => node.level,
(node) => node.expandable
);
treeFlattener = new MatTreeFlattener(
this._transformer,
(node) => node.level,
(node) => node.expandable,
(node) => node.dtoList
);
dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
}
I only want show something in console for every item is on "treeview" but show me this error
My code base on this project Stackblitz
*https://stackblitz.com/edit/angular-rtzh5a?file=src%2Fapp%2Ftree-flat-overview-example.html
Cannot read properties of undefined (reading "forEach")
Meaning that there is a place in your code, where you are using foreach on some array, which is null or undefined. Provided code sample doesn't contain this part, but if you will run app with 'ng serve' (on localhost), this console error will provide you also a component name and on which line problem occoured. For now it's saying main.js:1, because it's built version. You can easily secure it like this:
if (something) {
something.forEach(s => {
// ...
});
}
or use forof loops (like the example above, it just won't run when something is null/undefined)
for (let s of something) {
// ...
}
I am trying to get a text from an element with Cypress in the first test from the first domain and then type it in the second test in another domain, here is a code
I have to grab code from h4.
I implemented next part of code:
get studentCouponValue() {
return cy.get('h4').then(($span) => {
const couponValue = $span.text();
cy.log(couponValue);
})
}
in logs, I see the correct coupon's value, but when I am trying to type it into the field I get an error
The chain approach doesn't fit my expectation, cause i am going to use it in different tests.
Try this:
get studentCouponValue() {
return cy.get('h4').then(($span) => {
const couponValue = $span.innerText;
cy.log(couponValue);
})
}
i resolved
initStudentCouponValue() {
const self = this;
return cy.get('main > .container-fluid').find('h4').then((span) => {
self.couponValue = span.text();
cy.log('First log '+ self.couponValue);
return new Cypress.Promise((resolve) => {
return resolve(self.couponValue);
});
});
}
getStudentCouponValue() {
return this.couponValue;
}
in the test where we want to use value
let couponValue;
admin.initStudentCouponValue().then(() => {
couponValue = admin.getStudentCouponValue()
});
and later we can use
coupoValue
for inputs
I am debugging an app, there is an existing redux reducer which sets some data of store object. Now when i dispatch action for this reducer before the relevant object is initialised it still works and create an empty object. This works on our deployment server and do crash on my local machine with correct error that "map is undefined on null". Why is it creating an empty object and not crashing on deployment server and if it is creating an object why is it not assigning the data we pass to it. My reducer is
case ACTIONS.SET_LOCAL_WEIGHTS: {
const { weight } = action;
const drafts = fromJS(state.getIn(['draftData', 'rows']));
const setWeight = drafts.map((row: any) => {
row.data.weight = weight[row.id].weight;
return row;
});
return state
.setIn(['draftData', 'rows'], setWeight)
.setIn(['draftData', 'total'], setWeight.length);
}
It creates: draftData: {} when rows and total is also provided. I have tried it on node 15 and 12 for checking any anomaly on map function.
I get error Cannot read property 'map' of undefined on your code if the initial state doesn't have a property state.draftData.rows. I don't see anywhere where you would be creating an empty object.
The immutable.js fromJS method will create a List if called with an array from state.draftData.rows. But if it is called with undefined then it returns undefined instead of a collection with a .map() method.
I also don't think that you need to be calling fromJS if the rows object is never converted toJS, but it might depend on your initial state.
This code should work. It uses the existing List from state if it exists, or creates an empty List otherwise.
const drafts = state.getIn(["draftData", "rows"]) ?? fromJS([]);
The assignment in row.data.weight = weight[row.id].weight seems like a mutation of state.
I tried to rewrite this, but it seems strange to me that your code doesn't do anything with the weights in the payload unless their index/key matches one that's already in the state.
import { fromJS, List, Map } from "immutable";
interface Row {
data: {
weight: number;
};
id: number;
}
const reducer = (state = Map(), action) => {
switch (action.type) {
case ACTIONS.SET_LOCAL_WEIGHTS: {
const { weight } = action;
const drafts: List<Row> =
state.getIn(["draftData", "rows"]) ?? fromJS([]);
const setWeight = drafts.reduce(
(next, row, index) =>
next.setIn([index, "data", "weight"], weight[row.id]?.weight),
drafts
);
return state
.setIn(["draftData", "rows"], setWeight)
.setIn(["draftData", "total"], setWeight.size);
}
default:
return state;
}
};
I have a type:
type button = JSX.Element | null;
and a function:
const getFirstButton = (buttonArray: button[], first: boolean) => {
if (first) {
return buttonArray[1];
}
return buttonArray.find(b => b !== null);
};
here is my test
test('getFirstButton', () => {
const buttons = // what goes here?
expect(getFirstButton(buttons, false)).toContain('button_1');
});
I need help with the second line on the test. How do i handle this?
Is this even possible?
Note: my test file is test.ts and I don't want to change it .tsx
JSX.Element is an object created by JSX syntax, i.e. React.createElement.
It can be:
const buttons = [null, null, <p/>, <div/>];
expect(getFirstButton(buttons, false)).toBe(buttons[2]);
Notice that JavaScript arrays are zero-based, so buttonArray[1] is possibly a mistake that will be detected when covering if (first) condition.
I'm trying to encapsulate a TextInput such that when the value changes it does a serverside lookup and based on the result shows a notification to the user: "That group name already exists". I've been using this as my example to start from: https://marmelab.com/admin-on-rest/Actions.html#the-simple-way
My current error is
Error: The TextInput component wasn't called within a redux-form . Did you decorate it and forget to add the addField prop to your component? See https://marmelab.com/admin-on-rest/Inputs.html#writing-your-own-input-component for details.
but even if I add in
NameLookupTextInput.defaultProps = {
addField: true, // require a <Field> decoration
}
I still get the error. Heres my code
class NameLookupTextInput extends TextInput {
handleChange = eventOrValue => {
console.log("handleChange",eventOrValue);
this.props.onChange(eventOrValue);
this.props.input.onChange(eventOrValue);
if(this.timeoutHandle){
clearTimeout(this.timeoutHandle);
}
console.log(fetch);
this.timeoutHandle = setTimeout(function(){
let value = this.props.input.value;
fetchUtils.fetchJson(API_ENDPOINT+'/groupNameCheck/'+value, { method: 'GET'})
.then((data) => {
console.log(data);
let exists = data.json.exists;
let name = data.json.name;
if(exists){
console.log(this.props.showNotification('The group name "'+name+'" already exists.'));
}else{
console.log(this.props.showNotification('The group name "'+name+'" does not exist.'));
}
})
.catch((e) => {
console.error(e);
//showNotification('Error: comment not approved', 'warning')
});
}.bind(this),500);
};
}
export default connect(null, {
showNotification: showNotificationAction
})(NameLookupTextInput);