Setup for ember-cp-validations - validation

I'm trying to integrate ember-cp-validations to my project, so far now the code runs k but when i try to run "validate" methods i receive this error
Uncaught TypeError: Validator.getDependentsFor is not a function
I tracked down the error to this line
https://github.com/offirgolan/ember-cp-validations/blob/v2.9.3/addon/validations/factory.js#L436
const dependents = Validator.getDependentsFor(attribute, options) || [];
which tries to call a function getDependentsFor on a Validator object returned here
https://github.com/offirgolan/ember-cp-validations/blob/v2.9.3/addon/validations/factory.js#L434
const Validator = type === 'function' ? BaseValidator : lookupValidator(owner, type);
as type equals to "presence" it looks for the validator using lookupValidator and it's found but the class returned does not have the function getDependentsFor, i'm not sure if this is a bug or i'm missing something :/
Versions
Ember : 2.5.1
Ember Data : 2.6.1
ember-cp-validations : 2.9.3
import { validator, buildValidations } from 'ember-cp-validations';
const Validations = buildValidations({
email: [
validator('presence', true),
validator('format', { type: 'email', allowBlank: true })
]
});
var User;
User = DS.Model.extend(Validations, {
...
})
Any help will be appreciated!
Thanks in advance!!!

Related

Function implementation showing type error in Cypress while running tests

I am working on cypress for web application automation and having an issue with accessing a function from an object.
The code below is from a javascript file in 'e2e' folder.
class productsDemo {
pageObjects = {
productName: () => cy.get('.product-name-input'),
productDescription: () => {
cy.get('.product-description-input');
},
productCode: () => cy.get('.product-code-input')
}
inputProdName(prodname) {
this.pageObjects.productName().type(prodName);
}
inputProdDesc(proddesc) {
this.pageObjects.productDescription().type(proddesc);
}
}
module.exports = new productsDemo();
The code below is from a cypress test file to import and use the class.
import productsDemo from '../pageClasses/products.js'
describe('Product Creation', () => {
it('Create new Product', () => {
cy.visit('http://localhost:3000/products');
productsDemo.inputProdName('Laptop');
productsDemo.inputProdDesc('Electronics');
productsDemo.pageObjects.productCode().should('have.text', 'XXX124');
}
})
While running this file, getting this error in test runner.
Cannot read properties of undefined (reading 'type')
And, this type error is showing in the javascript file for 'inputProdDesc' function.
If the function declaration in 'pageObjects' object from the javascript file is modified as follows, then it works without problems:
productDescription: () => cy.get('.product-description-input'),
Could anyone help me to understand what is the issue with this code in setting value for 'product description' and how and to resolve this?
productDescription: () => {
cy.get('.product-description-input');
},
You have simply missed out the return statement from your page object class method call.
This is how it should look
productDescription: () => {
return cy.get('.product-description-input');
},
Without that return statements the code thinks you are returning undefined and that is the error message it is giving you:
Cannot read properties of undefined

Sails.js and Waterline: dynamic validation by DB request

I use Sails 11.1 and Waterline 2.11.2 with a MongoDB database.
I would like to validate data inserted in my "Article" model using a in validator for 1 attribute.
Before, I was doing the job with lifecycle callbacks (beforeCreate and beforeUpdate especially), but it makes double code.
Here you have the model, truncated with just the attribute in question :
module.exports =
{
schema: true,
autoCreatedAt: false,
autoUpdatedAt: false,
attributes:
{
theme:
{
model: 'Theme',
required: true
}
}
}
I know how to define it statically:
in: ['something', 'something other']
I know how to call constants I defined in my constants.js file :
defaultsTo: function ()
{
return String(sails.config.constants.articleDefaultTheme);
}
But I would like to get all themes in my DB, to have a dynamic in validation. So, I wrote this :
theme:
{
model: 'Theme',
required: true,
in: function ()
{
Theme.find()
.exec(function (err, themes)
{
if (err)
{
return next({ error: 'DB error' });
}
else if (themes.length === 0)
{
return next({ error: 'themes not found' });
}
else
{
var theme_ids = [];
themes.forEach(function (theme, i)
{
theme_ids[i] = theme.theme_id;
});
return theme_ids;
}
});
}
}
But it's not working, I have always the "1 attribute is invalid" error. If I write them statically, or if I check in the beforeCreate method with another DB request, it works normally.
If I sails.log() the returned variable, all the themes ids are here.
I tried to JSON.stringify() the returned variable, and also to JSON.parse(JSON.stringify()) it. I also tried to convert the theme.theme_id as a string with the String() function, but nothing else...
What am I doing wrong? Or is it a bug?
You can also check my question here : Waterline GitHub issues
Models's configuration at your attributes scope at in field of course will throw an error, because it should not use a function, especially your function is not return anything, also if you force it to return something, it will return Promise that Theme.find()... did.
Try use different approach. There are exist Model Lifecycle Callbacks. You can use something like beforeCreate, or beforeValidate to manually checking your dynamic Theme, if it's not valid, return an error.
Or if it's achievable using standard DB relation, just use simple DB relation instead.

sails.js model validation in bootstrap function

I have a model in sails.js and before creating a new record, I want to validate the data that I wanna insert in model.
this is my model for example :
module.exports = {
attributes: {
levelNumber : {
type : 'string',
defaultTo : '',
required : true,
unique : true
}
}
}
and this is my code that I put in bootstrap.js to run :
MODELNAME.validate({
levelNumber: 10
}, function(err){
if (err && err.invalidAttributes) {
console.log(err.invalidAttributes);
} else {
// model is valid
console.log('validate');
}
});
it always return "validate" and never return error in validation!!!!
my questions is :
1 - how we can validate and input json for a model before creating it ?
thx
Is there a reason to put application logic to bootstrap.js? The fact is sails executed it before the app is lifted, so it is not strange that something is not working correctly.
You can simply add beforeCreate function to your Model definition under api/models
your model will look like this
module.exports = {
attributes: {
.....
},
beforeCreate: function(values, next) {
// Validate the values HERE!!
}
};

Mongoose conditional required validation

I'm using mongoose and trying to set a custom validation that tells the property shall be required (ie. not empty) if another property value is set to something. I'm using the code below:
thing: {
type: String,
validate: [
function validator(val) {
return this.type === 'other' && val === '';
}, '{PATH} is required'
]}
If I save a model with {"type":"other", "thing":""} it fails correctly.
If I save a model with {"type":"other", "thing": undefined} or {"type":"other", "thing": null} or {"type":"other"} the validate function is never executed, and "invalid" data is written to the DB.
As of mongoose 3.9.1, you can pass a function to the required parameter in the schema definition. That resolves this problem.
See also the conversation at mongoose: https://github.com/Automattic/mongoose/issues/941
For whatever reason, the Mongoose designers decided that custom validations should not be considered if the value for a field is null, making conditional required validations inconvenient. The easiest way I found to get around this was to use a highly unique default value that I consider to be "like null".
var LIKE_NULL = '13d2aeca-54e8-4d37-9127-6459331ed76d';
var conditionalRequire = {
validator: function (value) {
return this.type === 'other' && val === LIKE_NULL;
},
msg: 'Some message',
};
var Model = mongoose.Schema({
type: { type: String },
someField: { type: String, default: LIKE_NULL, validate: conditionalRequire },
});
// Under no condition should the "like null" value actually get persisted
Model.pre("save", function (next) {
if (this.someField == LIKE_NULL) this.someField = null;
next()
});
A complete hack, but it has worked for me so far.
Try adding this validation to the type attribute, then adjust your validation accordingly. E.g.:
function validator(val) {
val === 'other' && this.thing === '';
}
thing: {
type: String,
required: function()[{
return this.type === 'other';
}, 'YOUR CUSTOM ERROR MSG HERE']
}

Breeze client-side custom validation with server-side data

I created a custom validator that check if a username is used on a DB.
The whole process of validation works. What is not working is result.
function createExistingUsernameValidator() {
var name = 'existingUsernameValidator';
var ctx = { messageTemplate: 'Questa partita I.V.A. o codice fiscale sono giĆ  stati inseriti.', displayName: "Partita IVA o Codice Fiscale" };
var val = new Validator(name, valFunction, ctx);
return val;
function valFunction(value, context) {
var result = ko.observable(true);
require('services/datacontext').getIsUserByUsername(value, result)
.then(function () {
debugger;
return !result();
});
}
}
The promise works: I know because it hits the debbugger line and the retunrnig value is correct.
But the validator always evaluate as false because I'm not returning anything when the validator is called. In other words: it won't wait for the promise.
Is it my bad javascript or something else?
Any help is welcome.
Thank you!
Edited after answer
I've come to a solution that involves Knockout Validation (very useful script).
function createIsExistingUserKoValidation() {
ko.validation.rules['existingUsername'] = {
async: true,
validator: function (val, params, callback) {
if (val) {
var result = ko.observable();
require('services/datacontext').getIsUserByUsername(val, result)
.then(function () {
callback(!result());
});
}
},
message: ' Existing username.'
};
ko.validation.registerExtenders();
}
In the entity creation:
var createDitta = function () {
var ditta = manager.createEntity(entityNames.ditta,
{
id: newGuid(),
legaleRappresentante: createPersona(),
isAttiva: true
});
ditta.pivaCodFiscale.extend({ existingUsername: { message: ' Existing username.', params: true } });
ditta.pivaCodFiscale.isValidating(false);
return ditta;
};
ditta.pivaCodFiscale.isValidating(false); this is needed because isValidating is initialized with true.
The problem is that your valFunction as written will ALWAYS return 'undefined'. ( which is 'falsy'.
The 'return !result()' expression is NOT the return value of 'valFunction', it is simply the result of an anonymous function that executes AFTER valFunction has already returned. This is the async nature of promises.
What you are trying is to write an 'asynchronous' validation which is NOT supported out of the box with Breeze, but the idea IS a good one.
I think that you might be able to accomplish what you want by having your async callback actually 'set' a value on the entity and have that set operation itself trigger a seperate 'synchronous' validation.
This IS a good idea for Breeze to support more naturally so please feel free to add a feature request to the Breeze User Voice for something like "asynchonous validation". We use this to gauge the communities interest in the various proposed features/extensions to Breeze.

Resources