cy.clear() not clearing input field properly - Cypress - vue.js

When I perform
cy.get('#fsp-name').clear().type('random text');
If the text already has value lets say 'assd asd adsdsd' and I perform above command I get something similar to 'random textassd'
I also tried using
cy.get('#fsp-name').clear().should('have.value', '').type('random text');
It works some time and in other times it complains it does not equal to ' '.
And I am trying to do this in a each loop like below
const data = [
{selector:'#name', newValue: 'John'},
{selector:'#phone', newValue: '1234567'}
];
cy.wrap(data).each(field => {
cy.get(field.selector).clear().should('have.value', '').type(field.newValue);
cy.contains('Save').click();
cy.visit('/abc/sdd');
cy.get(field.selector).invoke('val').should('equal', field.newValue);
});

Tried the solutions provided above, but all did not help.
I've ended up using this:
cy.get('#my-input-element').focus().clear();
If that doesn't work, the not so happy workaround is:
cy.get('#my-input-element').invoke('val', '');
When .type somehow did not finish the given string (rare cases):
cy.get('#my-input-element').invoke('val', 'Some text here');

I had a similar problem and It was related to focused and click related. I can suggest trying the following two option. I DON'T know it is right or wrong.
cy.get('#fsp-name').click().clear().type('random text');
OR
cy.get('#fsp-name').click().focused().clear().type('random text');
I was talking to the developer and according to him we are using MaterialUI and have some default component using focused and click event differently. After having both options resolved my problem

.clear() is an alias of .type('{selectall}{backspace}') however depending upon the input field set up this would not work in all cases.
I solved this by using .type('{selectall}{backspace}{selectall}{backspace}') instead of the .clear()

I'm using Cypress version 3.8.3 and I noticed that I have to invoke clear() sometimes two times in a row:
cy.get('#fsp-name').clear();
cy.get('#fsp-name').clear();

Seems like the cypress test runner is getting ahead of app initialization and some helpful article links below
https://www.cypress.io/blog/2018/02/05/when-can-the-test-start/
https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
As of now adding wait before clearing makes the test pass. Let me know if anyone has better solutions

I've had the same problem using Mui React with Cypress and when I called clear an ";" was added.
I've applied the same #Steven Vachon solution calling clear() function of cypress first.
Here my solution:
const clearInputElement = (input) => {
const input2Search = input;
cy.get(input2Search).clear();
cy.get(input2Search).then(($elm) => {
const event = new Event(input2Search, { bubbles: true, cancelable: true });
const input = $elm.get(0); // `as HTMLInputElement` for TypeScript
input.value = "";
input.dispatchEvent(event);
});
};

I ended up having to do clear manually via the DOM:
cy.get('input').then($elm => {
const event = new Event('input', { bubbles: true, cancelable: true });
const input = $elm.get(0); // `as HTMLInputElement` for TypeScript
input.value = '';
input.dispatchEvent(event);
});

I, too, faced a similar issue while using with react-ace editor. I wind up with
function typeContentOnSelectingExistingContent(elementId, content) {
return cy.get(`#${elementId}`).type(`{selectAll}{selectAll}${content}`)
}

Try this, it worked for me:
cy.get('#fsp-name').clear({ force: true }).then(() => {
cy.wait(3000)
cy.get('#fsp-name').invoke('val', '').type(`${valueToBeTyped}{enter}`)
})

Official docs states that:
It is unsafe to chain further commands that rely on the subject after .clear().
That's probably why the code in the original question didn't work, it was chaining clear and type commands:
cy.get('#fsp-name').clear().type('random text');
So, a simple alternative would be something like:
cy.get('#fsp-name').clear()
cy.get('#fsp-name').type('some text')
More about the clear command:
https://docs.cypress.io/api/commands/clear

Related

Understanding React-Admin translation

I am working with react-admin and trying to traduce it to my native language with this short guide usage:
https://github.com/marmelab/react-admin/tree/master/packages/ra-language-french
I keep getting non-referenced keys on the supposed translated keys.
To get my traduction working, I tried to delete node-modules file, tested in other browsers, cleared cache etc. but I still had the non-referenced keys: ra.______
When I changed this line (as below), it solved my problem:
const messages = { 'fr': frenchMessages, };
TO
const messages = { 'en': frenchMessages, };
And that's the only thing that i needed to change for the polyglot to work (French traduction).
Can someone explain to me what's going on, i don't know why it works in that case ?
Example in picture which shows the case explained above:
Not working case
Working case
Thanks for your time.
The <Admin locale='fr' ... property is deprecated! New version:
import { resolveBrowserLocale } from 'react-admin'
...
const i18nProvider = polyglotI18nProvider(locale => messages[locale], resolveBrowserLocale()) // or 'fr'

Checking button text matches a certain string in Nightwatch.js

I'm having a heck of a time trying to write a test where I check that text on a button matches a certain string. I tried ".valueContains", ".attributeContains" and got blank or null, and I've tried getText(), but that only seems to return an object.
I feel like it's something obvious I'm missing, so any help would be appreciated!
Based on what you have written so far in your question, I am wondering if there is there a reason you cannot use .containsText?
.waitForElementVisible('.yourclass', this.timeout)
.assert.containsText('.yourclass', 'Text of Button you expect to match')
http://nightwatchjs.org/api#assert-containsText
Without actually looking at the code its little difficult to predict whats going on. However all of the methods in selenium return a promise, so you need to wait for it to resolve.
function async getTextOfButton() {
const element = await driver.findElement(By.className('item-class'));
const text = await element.getText();
}
If you are not using async/await you could do
driver.findElement(By.className('item-class')).then(function(element) {
element.getText().then(function(text) {
console.log(text);
});
});

Vue 2 About nextTick

I have read that nextTick allows codes to be executed at the next action. But this does not work in my code, can someone helps me on this? Please correct me. Thanks.
.vue
.....
methods:{
getUserInfo(){
var vm = this
vm.$http.get('/getAuthUser').then((response)=>{
vm.user = response.data
})
Vue.nextTick(()=>{
vm.$http.get('/getShop/'+vm.user.id).then((response)=>{
vm.shop = response.data.data.shop
})
})
},
}
.....
{{user.id}} does work. where this gives me the following error:
GET http://localhost:8000/getShop/undefined 404 (Not Found)
EDIT#1
if i do something like this it works but this should not be the right way to do in my opinion.
.....
methods:{
getUserInfo(){
var vm = this
vm.$http.get('/getAuthUser').then((response)=>{
vm.user = response.data
vm.$http.get('/getShop/'+vm.user.id).then((response)=>{
vm.shop = response.data.data.shop
})
})
},
}
.....
EDIT#2
If I do something like this it wont work coz vm.user.id is not set.
.....
methods:{
getUserInfo(){
var vm = this
vm.$http.get('/getAuthUser').then((response)=>{
vm.user = response.data
})
vm.$http.get('/getShop/'+vm.user.id).then((response)=>{
vm.shop = response.data.data.shop
})
},
}
.....
I think your understanding of what nextTick does is incorrect. If you read the documentation, it says that the callback you pass to the nextTick function will be executed after the next DOM update.
Let's say you have a property that determines whether an element exists or not in the DOM with a v-if directive. If you change the value of the property so that the element exists in the DOM, you might have to wait for Vue to process the change and update the DOM before you can grab a reference of that element, for example. In that case, you should use Vue.nextTick to make sure by the time you want to query the DOM to get that element, it actually exists.
Your scenario doesn't have anything to do with the DOM.
You have 2 asynchronous HTTP calls that you want to execute one after another, because the second relies on the result of the first. Your original implementation and third one (EDIT#2) are flaky because you don't make sure the first HTTP request is complete before firing the second one, which explains why you get errors about vm.user.id not being set.
Your second implementation (EDIT#1) is more correct because the second HTTP request is fired after the first one completes. Still, I'd suggest a minor modification:
getUserInfo() {
vm.$http.get('/getAuthUser')
.then(response => {
vm.user = response.data;
return vm.$http.get('/getShop/' + vm.user.id);
}).then(response => {
vm.shop = response.data.data.shop;
});
}
The first callback returns a Promise which result is fed into the second then call. I like this approach because it avois having nested thens. I would also suggest you to read the MDN docs on Promises.

phantomjs global variables call in page.evaluate

I want to know how to use a varaible globally in phantomjs so that it can be used in the page.evaluate function also.
I have gone through some previous answers but but able to understand well
JSON-serializable arguments can be passed to page.evaluate.
Here is a very basic the following example using this technique :
page.open('http://stackoverflow.com/', function(status) {
var title = page.evaluate(function(s) {
return document.querySelector(s).innerText;
}, 'title');
console.log(title);
phantom.exit();
});

dojo - programmatic way to show invalid message

dojo newbie - giving it a shot.
After submitting a form, If an error is returned from the server I would like to show that message on the dijit.form.ValidationTextBox
var user_email = dijit.byId("login_user_email");
user_email.set("invalidMessage", data["result"]["user_email"]);
//need to force show the tooltip but how???
Any help much appreciated.
See it in action at jsFiddle.
Just show tooltip:
var textBox = bijit.byId("validationTextBox");
dijit.showTooltip(
textBox.get("invalidMessage"),
textBox.domNode,
textBox.get("tooltipPosition"),
!textBox.isLeftToRight()
);
Temporarily switch textBox validator, force validation, restore the original validator:
var originalValidator = textBox.validator;
textBox.validator = function() {return false;}
textBox.validate();
textBox.validator = originalValidator;
Or do both at once.
I think you can show the tooltip via myVTB.displayMessage('this is coming from back end validation'); method
you need to do the validation in the validator-method. like here http://docs.dojocampus.org/dijit/form/ValidationTextBox-tricks
you also need to focus the widget to show up the message! dijit.byId("whatever").focus()
#arber solution is the best when using the new dojo. Just remember to set the focus to the TextBox before calling the "displayMessage" method.
I am using dojo 1.10 which works create as follows:
function showCustomMessage(textBox, message){
textBox.focus();
textBox.set("state", "Error");
textBox.displayMessage(message);
}
Dojo reference guid for ValidationTextBox: https://dojotoolkit.org/reference-guide/1.10/dijit/form/ValidationTextBox.html
I know this question is ancient, but hopefully this'll help someone. Yes, you should use validators, but if you have a reason not to, this will display the message and invalidate the field:
function(textbox, state /*"Error", "Incomplete", ""*/, message) {
textbox.focus();
textbox.set("state", state);
textbox.set("message", message);
}
You can call directly the "private" function:
textBox._set('state', 'Error');
You get the same result as #phusick suggested but with less code and arguably in a more direct and clean way.
Notes:
_set is available to ValidationTextBox as declared on its base class dijit/_WidgetBase.
Live demo:
http://jsfiddle.net/gibbok/kas7aopq/
dojo.require("dijit.form.Button");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.Tooltip");
dojo.ready(function() {
var textBox = dijit.byId("validationTextBox");
dojo.connect(dijit.byId("tooltipBtn"), "onClick", function() {
dijit.showTooltip(
textBox.get('invalidMessage'),
textBox.domNode,
textBox.get('tooltipPosition'), !textBox.isLeftToRight()
);
});
dojo.connect(dijit.byId("validatorBtn"), "onClick", function() {
// call the internal function which set the widget as in error state
textBox._set('state', 'Error');
/*
code not necessary
var originalValidator = textBox.validator;
textBox.validator = function() {return false;}
textBox.validate();
textBox.validator = originalValidator;
*/
});
});