How to chain a custom function to express-validator? - express

I am using express-validator and I have chained some validations to link parameter like this:
route.post('/landing-pages/:link/blocks',
[
param('link').trim().escape().isString()
],
controller.addBlocks);
I need to add some chained functions like trim and escape to be able to modify the value.
I can use custom method like the following to add new validation:
route.post('/landing-pages/:link/blocks',
[
param('link').trim().escape().isString().custom((value, { req, location, path }) =>
{
//return true/false based on custom validation.
}
],
controller.addBlocks);
But instead of validating and returning true/false, I want to modify value and change it's original source exactly the way that trim or escape is doing it. for example, I want to replace some characters or I want to remove some words, etc.
Is there anyway to do it with express-validator?

you can chain customSanitizer function for that purpose
param('link').trim().escape().isString().customSanitizer(value => {
// imagine we have a sanitizer function
const sanitizedLink = linkSanitizer(value)
return sanitizedLink;
})

Related

How could I do not repeat the selection process in Cypress?

How could I do not repeat the selection process in Cypress?
E.g. if I have:
cy
.get("...").find("...")...eq(0)...should("...")
.get("...").find("...")...eq(1)...should("...");
How could I avoid duplicating the .get("...").find("...")... part if at some point I need to pick either the eq(0) or the eq(1)?
You can use .as() to alias an element.
// Just aliasing the base
cy.get('foo').find('bar').as('something');
cy.get('#something').eq(0).should('exist');
cy.get('#something').eq(1).should('exist');
// aliasing the specific elements
cy.get('foo').find('bar').eq(0).as('firstEl');
cy.get('#firstEl').should('exist');
cy.get('foo').find('bar').eq(1).as('secondEl');
cy.get('#secondEl').should('exist');
You could also use a custom command.
// If the selectors in `get` and `find` are constant, you could do a custom command
Cypress.Commands.add('myGet', (index) => {
return cy.get('foo').find('bar').eq(index);
})
cy.myGet(0).should('exist');
// Or if you wanted to be able to customize the get and find
Cypress.Commands.add('myGet', (get, find, index) => {
return cy.get(get).find(find).eq(index);
})
cy.myGet('foo', 'bar', 0).should('exist');
You can create a custom command for this. Go to cypress/support/commands.js and write:
Cypress.Commands.add('selectElement', (index) => {
cy.get('selector').find('selector').eq(index).should('be.visible')
})
And then in your test just write:
cy.selectElement(1)
cy.selectElement(2)

Cypress Get Attribute value and store in Variable

I want to get the Attribute value and store in a variable how we can achieve this in cypress
In my case I want to get the complete class value and store it in variable.
This code just give me the attribute class value but how I can store the fetch value in variable
cy.get('div[class*="ui-growl-item-container ui-state-highlight ui-corner-all ui-shadow ui-growl-message"]').invoke('attr', 'class')
I was trying to compare the style of one element with another to make sure they were equal. Here's the code that seems to work for me.
cy.get('.searchable-group-selector-card-image')
.eq(4)
.invoke('attr', 'style')
.then(($style1) => {
const style1 = $style1
})
A good way to solve this kind of scenario is to use the alias mechanism. One could leverage this functionality to enqueue multiple elements and then check all of them together by chaining the results. I've recently come to a case in an SPA where the assertion had to happen between elements that were spread across different angular routes (call them different pages).
In your use case, this would like:
cy.get('.searchable-group-selector-card-image')
.eq(4)
.invoke('attr', 'style')
.as('style_1')
cy.get('.another-element')
.invoke('attr', 'style')
.as('style_2')
// later on for example you could do
cy.get('#style_1').then(style_1 => {
cy.get('#style_2').then(style_2 => {
// Both values are available and any kind of assertion can be performed
expect(style_1).to.include(style_2)
});
});
This is described in Variables and Aliases section of the Cypress Documentation.
Here is how I got the value of for attribute in a label tag which had text "Eat" inside.
cy.contains('Eat').then(($label) => {
const id = $label.attr('for');
}
Most important thing is to get the selector right, so it exactly finds the value you are looking for. In this case you already found it. By using then() gives you the ability to store it in a variable.
cy.get('div[class*="ui-growl-item-container ui-state-highlight ui-corner-all ui-shadow ui-growl-message"]').invoke('attr', 'class')
.then($growl-message => {
const message = $growl-message.text()
//do the checks with the variable message. For example:
cy.contains(message)
})
Note that the scope of the variable is within the curly brackets. Thus using the variable has to be within those curly brackets.

Vuetify how to add/remove rule dynamically

I'm using vuetify validation, and i have three date fields: Month, From, To. I need to add required rule according to the following:
If Month selected - From and To not required.
If any of From or To selected - Month not required.
I tried computed() method, to check if From or To are null, but it seems like :rules set once, and then not change.
computed: {
monthRules() {
return this.searchForm.from ? [] : [factory.required()];
},
Here's some code
<date-field
ref="month"
v-model="searchForm.month"
:rules="monthRules"
>
</date-field>
<date-field
ref="from"
v-model="searchForm.from"
#input="validateTo"
:rules="fromRules"
>
</date-field>
<date-field
ref="to"
v-model="searchForm.to"
:rules="toRules"
>
</date-field>
monthRules: [factory.required()],
fromRules: [],
toRules: [
*some rules from factory here*
],
factory
required() {
return v => !!v || 'Field is required';
},
Is it possible to dynamically build an array of rules? Or is there a better way
I am not very clear on Vuetify rules as I think it's better to use a specialized library like vee-validate which already has a ton of pre-defined rules, for something like this. As for the dynamic rules, the best way to go about would be to use an object binding like so:
:rules="{
required: requiredBool
}"
Where requireBool is your computed property. Again, as I said, I am not very familiar with Vuetify rules, but this works like a charm with Vee-Validate.

Find matching elements in array and do something for each match

I'm a little overwhelmed by all the functions available to me in Lodash, so I hope someone can point me to the one I'm sure exists which will do the following for me. I want to be able to pass an array and a search condition, and have it loop through all the matched items, allowing me to run a function for each. What I have at the moment is something akin to this:
_.each(myArray, (item) => {
if (item.field=="whatever") {
console.log("Matched by "+item.name);
}
});
This works fine, of course. It's just that I'm sure Lodash has a way for me to move the item.field=="whatever" into the function arguments somehow, and I'd prefer to go with the more idiomatic Lodash way if I can.
It's just that I'm sure Lodash has a way for me to move the item.field == "whatever" into the function arguments somehow
If you want to find all the matching items in an array based on the arguments you pass in, then you could use the _.filter method, which can use the _.matches shorthand internally:
_.filter(myArray, { field: 'whatever' });
However, you would still need to loop over the items if you want to do something for each match:
_.each(_.filter(myArray, { field: 'whatever' }), item => {
console.log("Matched by " + item.name);
});
Alternatively, if you want a different way of writing this, you can wrap the filtered items with the lodash object wrapper, _(), which essentially enables chaining, thereby allowing you to chain the _.each() method:
_(_.filter(myArray, { field: 'whatever' })).each(item => {
console.log("Matched by " + item.name);
});
Or a more readable version:
var matchedItems = _.filter(myArray, { field: 'whatever' });
_(matchedItems).each(item => {
console.log("Matched by " + item.name);
});
Personally, I would probably just keep what you originally wrote since it's short, readable and easy to maintain.

How to append a GET parameter to all urls using Phalcon

Given a page retrieved at for example:
http://myapp.dev/path/subfolder?param=abc
Whenever the additional GET parameter called param is present it should be added automatically to all subsequent links in my navigation as constructed in the .volt template. For example:
Go to subfolder 2
I.e. based on this .volt link the the goal is to generate:
Go to subfolder 2
If you want to append Query string parameters only for given links you can go with Luke's solution.
However I think you want to achieve something a bit different and it involves custom logic. For this to happen we should create a custom Volt function.
Custom function definition:
public static function urlFor($params, $queryStringParams = [])
{
$di = \Phalcon\DI::getDefault();
if ($di->getRequest()->has('param')) {
$queryStringParams['param'] = $di->getRequest()->get('param');
}
return $di->getUrl()->get($params, $queryStringParams);
}
The above function acts the same as url() function in Phalcon, it just allows us to write a bit of custom logic before passing the parameters to url().
In your case we check if URL contains desired query param and we add it to every URL generated on the current request. In my case the above function is in Helper file so I can use it anywhere I need to.
This is our View service definition:
$di->set('view', function() use ($di) {
$view = new \Phalcon\Mvc\View();
...
$view->registerEngines([
'.phtml' => function($view, $di) {
$volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
$options = [
'compiledPath' => $di->getConfig()->site->path->cache . 'volt/frontend/',
'compiledExtension' => '.php',
'compileAlways' => $di->getConfig()->debug,
];
$volt->setOptions($options);
...
// IMPORTANT PART: Overwriting default url() function in Volt
$compiler = $volt->getCompiler();
$compiler->addFunction('url', function($resolvedArgs, $exprArgs){
return 'Helpers\Common::urlFor(' . $resolvedArgs . ')';
});
return $volt;
}
]);
return $view;
});
Please note the IMPORTANT PART comment in the above code block.
Let us finish with example:
User is on this address:
http://myapp.dev/path/subfolder?param=abc
But somewhere in your code you want to generate a link to News page:
News
Our code will catch the param in the URL and will generate the following address:
http://myapp.dev/news/list?param=abc