How to use state in a cypress component test - ionic-framework

I am testing a form component in my cypress ionic component test, the form relies on text and setText props which are provided by the page, which is to say there is no state handled by the component itself only the page, how can I recreate the state normaly provided in the context of a component test,
Thank you
<SmartTextField
text={""}
setText={(text: string) => {
// output of typing
}}
/>;
I have tried to add useState but get the error Cannot read properties of null (reading 'useState')

Related

Why not prepopulated value being set as value in Autocomplete Material UI using controller of react-hook-form

I am using controller component of react-hook-form to call material UI autocomplete.
When I'm passing defaultValue parameter then it is populating in field but when click on submit button then showing validation error message:
shared_with_users must be a `array` type, but the final value was: `null` (cast from the value `{ "value": "571998", "label": "\"Satyendra Kumar\"" }`). If "null" is intended as an empty value be sure to mark the schema as `.nullable()`
Here is my code:
https://codesandbox.io/s/nervous-tree-9e2js?file=/src/App.js
Autocomplete is coming after selection of last select box. I am using yup for form validation.
Please suggest the fixes.
Thank you in advance
Issue is fixed now.
Problem was uncontrolled component, when i created controlled component then it started working properly.
Here is my updated code:
https://codesandbox.io/s/nervous-tree-9e2js?file=/src/App.js

Updating Angular 6 Form value in case corresponding dom native element value is modified by external library

I am experimenting cobrowsing with Angular 6 Forms.In co-browsing an opensource library togetherJS updates the DOM value of corresponding element for remote party.I have updated togetherJS related code in index.html(two line one in head and another in body) I have observed using ControlValueAccessor Form type DOM value of corresponding element is getting updated but FormControl value is not getting updated in view.
My question is how changes done by an external library on DOM elements can be reflected into angular 6 form control's element value in view.
One can get the code from below link:
https://github.com/srigaurav1986/Angular-Forms.git
How to reproduce:
1.Download code from above link.
2.Install dependencies using "npm install"
3.Run "ng serve -o"
4.open in browser "http://localhost:4200/controlvalueaccessor"
5.Click on "Start TogetherJs"
6.Copy the popped link in another browser window.
7.Update the "Name" field
We can see DOM field value is also getting updated on remote side but after pressing "Submit" button we can see FormControl value remains unaltered on remote side but changed on other side.
I tried using manually detecting changes using application.tick,markforcheck() and detectchanges() apis but no luck.Is there a way, where we can listen to some event on DOM element change and subscribe to it and also update the Formcontrol parameter values in such case.
The answer to this question lies in angular(6) property that it works on shadow DOM and only listen to the changes happening within angular zone , when the third party library like TogetherJS updates DOM corresponding changes doesn't effect angular components as they are not subscribe to actual DOM native element.
In order to resolve this issue we did following :
Register one call back in Form class constructer to capture DOM “change” events triggered from Co-Browsing library i.e. happening outside angular zone as mentioned below:
Code Snippet
constructor(private formBuilder: FormBuilder,private elementRef: ElementRef,private _renderer: Renderer,private cdr:ChangeDetectorRef,private app:ApplicationRef,private zone:NgZone) {
zone.runOutsideAngular(() =>{
window.document.addEventListener('change', this.change.bind(this));
})
}
Define the eventHandler to perform below actions :
Run in Angular context using this.zone.run()
Use ElementRef to get the component’s template selector.
Run queryselector on input elements and compare with event’s outerHTML to check which element has changed in component.
Set the Formcontrol’s value for matching element.
PS: Here customerForm is ControlValueAccesor FormGroup type of instance. In your case it can be your form. We can generalize form( In case reactive) key traversal as mentioned in another SO post
Angular 2: Iterate over reactive form controls
Code Snippet:
change(event){
event.preventDefault();
console.log("DOM value changed" ,event);
console.log("component value", this.elementRef.nativeElement);
this.zone.run(() => { console.log('Do change detection here');
//this.cdr.detectChanges();
if(this.elementRef.nativeElement.querySelectorAll('input')[0].outerHTML === event.target.outerHTML)
{
console.log('Inside value updation');
//this.customerForm.controls.name.value=event.target.value;
this.customerForm.controls['name'].setValue(event.target.value);
}
});
setTimeout(() =>{
this.cdr.markForCheck();
})
}
This will set the respective values of elements(obviously via traversing loop) changed in component and validation should not fail as it’s happening in current context.
The core idea of above details is how to capture change events happening outside angular zone and updating angular application accordingly.
PS : I shall update the full code in github for other's perusal.

Angular2 ControlGroup valueChanges on initial bind

I have a form with some <input type="text"> widgets and I have noticed that ControlGroup.valueChanges is being called upon initial databind when using [ngFormModel] and ngControl.
This means that the user thinks that the form has been changed upon initial load.
Is this normal or should I be using a different observable to track changes made the by the user?
I am using Angular2 RC3 and the following version import for forms:
import {ControlGroup, Validators, FormBuilder} from '#angular/common';
I think that's just how it works, however if you just want to track if changes are made by user, you should employ ControlGroup.dirty or formControl.dirty with the changes Observable.
ControlGroup.valueChanges.subscribe(() => {
if(ControlGroup.dirty){
console.log('This change is made by User.');
}
else {
console.log('This change is Automated. before any User interaction.');
}
})

How do you inspect a react element's props & state in the console?

React Developer Tools give a lot of power to inspect the React component tree, and look at props, event handlers, etc. However, what I'd really like to do is to be able to inspect those data structures in the browser console.
In chrome I can play with the currently selected DOM element in the console using $0. Is there a way to extract React component info from $0, or is it possible to do something similar with the React Dev Tools?
Using React Developer Tools you can use $r to get a reference to the selected React Component.
The following screenshot shows you that I use React Developer Tools to select a component (Explorer) which has a state-object callednodeList. In the console I can now simply write $r.state.nodeList to reference this object in the state. Same works with the props (eg.: $r.props.path)
An answer to your question can be found here in a similar question I asked:
React - getting a component from a DOM element for debugging
I'm providing an answer here because I don't have the necessary reputation points in order to mark as duplicate or to comment above.
Basically, this is possible if you are using the development build of react because you can leverage the TestUtils to accomplish your goal.
You need to do only two things:
Statically store the root level component you got from React.render().
Create a global debug helper function that you can use in the console with $0 that accesses your static component.
So the code in the console might look something like:
> getComponent($0).props
The implementation of getComponent can use React.addons.TestUtils.findAllInRenderedTree to search for match by calling getDOMNode on all the found components and matching against the passed in element.
Open console (Firefox,Chrome) and locate any reactjs rendered DOM element or alternatively execute js script to locate it:
document.getElementById('ROOT')
Then check for element properties in object property viewer for attributes with name beginning like '__reactInternalInstace$....' expand _DebugOwner and see stateNode.
The found stateNode will contain (if it has) 'state' and 'props' attributes which is used heavily in reactjs app.
Though the accepted answer works, and is a great method, in 2020 you can now do a lot of inspection without using the $r method. The Components tab of React DevTools will show you props and detailed state when you select the relevant component (make sure you're on the right level), as well as let you do other things like suspend it or inspect the matching DOM element (little icons in the top right).
Assign the state or prop object to the window object:
window.title = this.state.title
And then from the dev tools console you can try different methods on the exposed object such as:
window.title.length
8
You can attach a reference to the window object like
import { useSelector } from "react-redux";
function App() {
// Development only
window.store = useSelector((state) => state);
return (
<div className="App">
</div>
);
}
export default App;
Then access it from the console
store
{states: {…}}
states:
someProperty: false
[[Prototype]]: Object
[[Prototype]]: Object
[Console][1]
[1]: https://i.stack.imgur.com/A4agJ.png

How to use form validation in a form with a zone attribute?

I have a big problem with Tapestry 5.3.6..
I have a form with a custom simple mixins that implies that form's ids couldnt' be modified :/
So i have this :
<form t:type="form" t:id="formId" t:mixins="aMixins" t:zone="zoneID">
<t:errors/>
<input t:type="TextField"/>
<a t:type="LinkSubmit" t:id="linkId"/>
</form>
<t:zone t:id="zoneID">
Something....
</t:type>
When I use the zone form attribute, the validation errors aren't displayed, how can i make the validation errors displays errors without include the form into a zone ?
I can't include this form into a zone because when my mixin is initialized, it put some listeners on some DOM elements and when i submit my form, the form is reloaded (because of the zone) and reload the mixin too, which add some more listener on new DOM elements and after the submit an event is fired which is catched by corresponding listeners, but some of listeners are linked to unexistant elements and the js crash.
Thanks a lot for your reponses
1 .
I have a form with a custom simple mixins that implies that form's ids
couldnt' be modified
This is not implied. Maybe, it's your requirement?
If not then to plug in your mixin into ajax rendering you need to make the mixin a bit more flexible.
In YourMixin class:
#InjectContainer
private ClientElement element;
void afterRender() {
String elementId = element.getClientId();
JSONObject spec = new JSONObject();
spec.put("elementId", elementId);
jsSupport.addScript("new MixinHandler(%s)", spec.toString());
}
This is just a hint, take a look at Autocomplete implementation (class, javascript) for a complete sample.
2 .
When I use the zone form attribute, the validation isn't working
This sounds doubtful.. I guess validation errors are not visible because you do not update the form itself and its <t:errors/> tag.
This can be verified if you set break points into FAILURE and SUCCESS event handlers of the form in your page (see org.apache.tapestry5.EventConstants).