Required doesn't work after adding test Yup - reactjs

This is what i've done
subject: Yup.string().test('checkForManualText', 'Please, add hand-written subject as well',
function(inputValue) {
let newMessage = inputValue.replace(/\{{(.+?)\}}/gmi, '').replace('/\s/gmi', '').trim()
return newMessage.length !== 0
}).required()
Now the test validation works fine, but the required stopped working. Before adding test, all was good.

You don't need to use required when using .test. Returning false will show the error message. Just add null/undefined check to the string.
subject: Yup.string().test('checkForManualText', 'Please, add hand-written subject as well',
function(inputValue) {
if(!inputValue) return false;
let newMessage = inputValue.replace(/\{{(.+?)\}}/gmi, '').replace('/\s/gmi', '').trim()
return newMessage.length !== 0
})
Working Example

Related

Expect().toBe(true) condition in if statement not working as expected

I am using protractor with selenium and was trying to check the element present using the expect() condition with in the if statement, but it is going to else block even though the condition is true. In the condition I tried both toBe and toEqual and both has same effect.
let email_Original = element(by.css('button[value="original"][aria-pressed="true"]'))
var isTranslated = await email_Original.isPresent()
console.log('Translate button state is ' + isTranslated)
if (expect(isTranslated).toBe(true)) {
console.log('Pass: Email successfully translated to original language')
} else {
console.log('Fail: Email not translated to original language')
}
output
Translate button state is true
Fail: Email not translated to original language
I would get rid of the logging messages and just use the assertion to tell you if it passed or not.
it('should be translated', async () => {
const email_Original = element(by.css('button[value="original"][aria-pressed="true"]'));
const isTranslated = await email_Original.isPresent();
expect(isTranslated).toBe(true);
});

Yup (with formik and react) - Can't validate array length

kinda new to Yup and I can't figure out how to validate that an array is not empty.
I'm using react + formik + yup + material-ui
here is an example I've created:
https://codesandbox.io/s/new-fire-29onf?file=/src/App.js
I tried in the validationSchema to just use the required method:
validationSchema={Yup.object({ permissions : Yup.array().required('permission cant be empty') })}
i tried to add my functionally using the test method like this:
validationSchema={Yup.object({ permission: Yup.array().test ('notEmptyArr', 'array is empty', (value) =>{ console.log(value); return value.length > 0; }) })}
i also tried to add method to the array like this:
Yup.addMethod(Yup.array, "notEmpty", function(message) { return this.test("notEmpty", message, function(arr) { return Boolean( arr.length > 0 ); }); });
But none of that worked for me : (
if I remove the validation I see the value.permission is indeed an array, with values (if selected)
what am I doing wrong?
thanks
You can use .min():
validationSchema={Yup.object({
permissions: Yup.array().min(1)
})}
UPDATE / WARNING:
Previously only array().required() was required to make sure there was at leas 1 item in the array. For example [] would not pass the test.
⚠️ As of version 0.31.0 (2020-11-23) the behavior of array().required() changed! Now to make sure you have at least 1 item in the array you need to sure: array().required().min(1)
use array().min(1) to handle an empty array error instead of required(); if you use Formik to handle a custom message, use array().min(1, 'your message')

Using Jest and Enzyme to call a function

I am using Jest and Enzyme to test a React component. I am trying to test my form validation rules when submitting a form. The tests need to cover all possible cases of this function
const handleSubmit = event => {
event.preventDefault();
const { createPassword, confirmPassword } = event.target.elements;
if (createPassword.value !== confirmPassword.value) {
setPassValidationError("*Passwords must match!");
} else if (createPassword.value.length < 8) {
setPassValidationError("*Passwords must be at least 8 characters long!");
} else if (createPassword.value.search(/[A-Z]/) < 0) {
setPassValidationError(
"*Passwords must contain at least one uppercase letter!"
);
} else if (createPassword.value.search(/[!##$%^&*]/) < 0) {
setPassValidationError(
"*Passwords must contain at least one special character!"
);
} else {
props.updatePassword({
uid: props.uid,
token: props.token,
new_password: createPassword.value
});
event.target.reset();
}
};
This function is pretty straight forward createPassword and confirmPassword are the values for 2 different input fields. When the form is submitted and this function gets called I am testing the password on different criteria. If the password is not strong enough, the setPassValidationError hook is called and updates a state variable.
I am currently trying to test the function with a password shorter than 8 characters.
it("passwords must be 8 char long", () => {
const wrapper = mount(<NoAuthPasswordChange />);
const passInput = wrapper.find("#create-password");
const confirmPass = wrapper.find("#confirm-password");
passInput.simulate("change", { target: { value: "QQQQQQ" } });
confirmPass.simulate("change", { target: { value: "QQQQQQ" } });
const submitButton = wrapper.find("#submit-button");
submitButton.simulate("click");
expect(wrapper.find("#password-validation-error").text()).toContain(
"*Passwords must be at least 8 characters long!"
);
});
Jest is telling me that #password-validation-error cannot be found (expected 1 node found 0). Now this particular part of the code is only rendered if passValidationError has data.
{passValidationError ? (
<h2
className={styles.passwordError}
id="password-validation-error"
>
{passValidationError}
</h2>
) : null}
I'm not sure if I just have a simple bug in my test or if something more advanced needs to be done in order to use Jest and have a function call a hook update.
Edit: I am beginning to wonder if the event parameter required by the handleSubmit function is problematic due to the function being called by Jest.
This can be cause by not updating the component itself. Have you tried to force your wrapper to be re-rendered:
https://airbnb.io/enzyme/docs/api/ShallowWrapper/update.html
https://airbnb.io/enzyme/docs/api/ReactWrapper/update.html
I have found a solution to my issue. The test needs to call the form submission on the form element itself and not via a button click. So instead of submitButton.simulate("click") I need to simulate a submit on my form element. I am unsure why this solution works and the posted code does not.

How to validate with regular expression and display error message in xeditable

I am using xeditable in my project.
I need to validate each and every field,
how to do validation using ng-pattern="/^[a-zA-Z ]*$/" and show error message if the input value does not match the pattern.
can any one guide me how can i proceed with this.
Fiddle
$scope.checkName = function(data) {
console.log("user.name.onbeforesave:", data)
if (data !== 'awesome') {
return "Username should be `awesome`";
}
};
Do you need to use ng-pattern? Can you not change the function to use the regexp?
This works:
$scope.checkName = function(data) {
console.log("user.name.onbeforesave:", data)
if (!data.match(/^[a-zA-Z ]*$/)) {
return "Only spaces and letters allowed";
}
}

Failing To Check if Element is Disabled

I have a dropdown with elements that get disabled when conditions are met. In the test, I check them for being disabled, but all tests fail and always return the element state as enabled (Clearly incorrectly. I have ensured that this is not a timing issue - refreshed the page and gave ample wait time with browser sleep - the elements are clearly disabled on the screen). There is an anchor within a list item. Please see image:
I have tried checking both the list item and the anchor, like so:
var actionDropDownList = $$('[class="dropdown-menu"]').get(1);
var checkOutButtonState = actionDropDownList.all(by.tagName('li')).get(6);
actionsButton.click();
actionDropDownList.all(by.tagName('li')).count().then(function(count){
console.log('THE NUMBER OF ELEMENTS IN THE DROPDOWN IS...............................................................' + count);
}) //verify that I have the correct dropdown - yes
checkOutButtonState.isEnabled().then(function(isEnabled){
console.log('CHECKING checkOutButton BUTTON STATE: ' + isEnabled);
}) //log state - shows incorrectly
I have also tried checking the button itself for disabled state (the element below is what I tried checking instead of the list element):
var checkOutButton = $('[ng-click="item.statusId !== itemStatus.in || checkOut()"]');
This failed as well.
Not sure which one I should check and why both are failing. How do I correct this and get it to show that the disabled button is...well, disabled.
TEMPORARY ADD ON EDIT:
For simplicity's sake, I am trying:
var hasClass = function (element, cls) {
return element.getAttribute('class').then(function (classes) {
return classes.split(' ').indexOf(cls) !== -1;
});
var checkOutButtonState = actionDropDownList.all(by.tagName('li')).get(6);
expect(hasClass(checkOutButtonState, 'disabled')).toBe(true);
It still fails, however, despite the element clearly having the class. Alec - your solution throws "function is not defined," I am not sure if I need something else for it to see jasmine. Tried, but can't find anything wrong with it, not sure why I can't get it to work.
Edit:
If I run...since it only appears to have one class:
expect(checkOutButtonState.getAttribute('class')).toBe('disabled');
I get "expected 'ng-isolate-scope' to be 'disabled'"
In a quite similar situation I've ended up checking the presence of disabledclass:
expect(checkOutButtonState).toHaveClass("disabled");
Where toHaveClass() is a custom jasmine matcher:
beforeEach(function() {
jasmine.addMatchers({
toHaveClass: function() {
return {
compare: function(actual, expected) {
return {
pass: actual.getAttribute("class").then(function(classes) {
return classes.split(" ").indexOf(expected) !== -1;
})
};
}
};
},
});
});

Resources