How to test current date condition in behat? - testing

I have feature that is based on current date, and the question is if it is good solution to write if condition in scenario. Simple example: if tested date is equal to current then other field is equal to 0 else equal 10. Meybe there are libraries to mock current date time in symfony 4.

You could write a step like:
Then I should see sysdate with format "Y-m-d" in the "example" field
Then for your context:
public function iShouldSeeSysdateWithFormatInTheField(string $format, string $key)
{
$field = $this->getSession()->getPage()->findField($key);
$value = (new DateTime())->format($format);
if (is_null($field->getValue())) {
assertEmpty($value);
}
if($value != $field->getValue()) {
throw new Exception('date does not match');
}
}

Related

Express Validatior - How Do I Break The Validation Chain?

I have a date field that I want to ensure is in a valid format and if so is the user over 18. The format is YYYY-MM-DD.
Here is one of my validators - the one that is failing:
body('birthday', 'Date format should be: YYYY-MM-DD')
.isRFC3339()
.custom(date => {
const over18 = moment().diff(date, 'years') >= 18;
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),
Currently what happens is if the date is not a RFC3339 date the validation chain continues. This is problematic because moment produces an error if I pass an ill formatted date.
How do I break the chain after the call to .isRFC3339() so that if the date is invalid the custom validator will not run? I couldn't find anything in the docs
You can use momentjs strict mode together with String + Format parsing using moment.ISO_8601 (or moment.HTML5_FMT.DATE) special formats.
Your code could be like the following:
body('birthday', 'Date format should be: YYYY-MM-DD')
// .isRFC3339() // no more needed
.custom(date => {
const mDate = moment(date, moment.ISO_8601, true);
const over18 = moment().diff(mDate, 'years') >= 18;
if(!mDate.isValid()) {
return Promise.reject('Date is not YYYY-MM-DD');
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),

Siebel Business(E-script) Service Calculate Expiry Date

I have a requirement to create a business service function to calculate expiry date , 2 weeks from a date field in Siebel.
I have written the code in Java which is
public static Date checkexpiry(Date Datefield)
{
Calendar cal = Calendar.getInstance();
cal.setTime(Datefield);
cal.add(Calendar.DATE, -14);
Date twoWeeksToExpiry = cal.getTime();
System.out.println(twoWeeksToExpiry);
return twoWeeksToExpiry;
}
if current date is equal to twoWeeksToExpiry {do .....}
So how can I re-write this code on Siebel using a business service particularly E-script.
The whole idea is have an output Yes is its 2 weeks before a date field in Siebel.
This will later be used in a work flow.
OK so have started Migrating my Java coding skills to Siebel E-Script I came up with this.
function ExpiryNotification(Inputs,Outputs)
{
try
{
var expiryDate = Inputs.GetProperty("DateField");
var eDate= new Date(expiryDate);
var notificationdate = eDate-14;
var currentdate = Today();
if (currentdate==notificationdate){
Outputs.SetProperty("Notification", "Y")
}
else {
Outputs.SetProperty("Notification", "N")
}
catch(e)
{
TheApplication().RaiseErrorText(e.toString());
}
}
However I did not use the Business Service ..I used a calculated field on my Business Component.
The calculated Fields
1 twoWeeksToExpiry = Datefield-14
Notification = IIf (Today()==[twoWeeksToExpiry], "Y", "N")
So this solved the problem without scripting,
Will appreciate any suggestions on my scripting thou I didn't use it.

Formatted date filter in CGridView

I display my date in CGridView as: "22.6.2012 22:53" with:
array('name' => 'date',
'value' => date("j.n.Y G:i", strtotime($model->date))
),
But in my filter, I need to search in this format (which is in the database) to get results: "2012-06-22 22:53".
How can I make my filter to work in the format that is displayed in my CGridView? I've searched for an answer but haven't found one, I've also tried adding the date function in my model search() for this attribute:
$criteria->compare('date', date("j.n.Y G:i", strtotime($this->date), true);
but then I just get an empty list :)
Help would be greatly appreciated.
To begin with, you should not be using the value property to control the formatting of dates. The proper way is to set the type property to 'date' and, if you do not do this already, set CApplication.language to target the appropriate locale.
For the filter it would be best for the user if you use a CJuiDatePicker widget to let the user visually pick the date; there's a short and to-the-point guide on how to do that here.
Update:
Formatting columns with type == 'date' is done through CGridView.formatter, for which if you do not explicitly set a value the default is whatever the 'format' application component is. So you can specify and configure a CFormatter on the spot, or if you want to use the application's formatter but with slight modifications you can do
$formatter = clone Yii::app()->format;
$formatter->dateFormat = 'whatever'; // or $formatter->dateTimeFormat
and then assign this instance to CGridView.formatter.
compare() makes a sql sentence with the input, so I had to change the input to my wanted format.
my function:
function changeDateToDBformat($datum) {
if (strstr($datum, '.') || strstr($datum, ':')) {
$formats = array('!j.n', '!j.n.Y', '!j.n.Y H:i', '!n.Y H:i', '!n.Y', '!H:i', '!j.n.Y H', '!n.Y H', '!Y H:i', '!Y H');
$date = false;
foreach ($formats as $format) {
$date = DateTime::createFromFormat($format, $datum);
if (!($date === false)) {
$izbraniFormat = $format;
break;
}
}
if (!$date === false) {
$datum1 = $date->format('Y-m-d H:i');
$date2 = DateTime::createFromFormat(substr($izbraniFormat, 1, strlen($izbraniFormat)), $datum);
$datum2 = $date2->format('Y-m-d H:i');
$datumcas1 = explode(' ', $datum1);
$datumcas2 = explode(' ', $datum2);
$prvidatum = explode('-', $datumcas1[0]);
$drugidatum = explode('-', $datumcas2[0]);
$koncniDatum = '';
for ($a = 0; $a < sizeof($prvidatum); $a++) {
if ($prvidatum[$a] == $drugidatum[$a])
$koncniDatum .= '-' . $prvidatum[$a];
}
$koncniCas = '';
$prvicas = explode('-', $datumcas1[1]);
$drugicas = explode('-', $datumcas2[1]);
for ($a = 0; $a < sizeof($prvicas); $a++) {
if ($prvicas[$a] == $drugicas[$a])
$koncniCas .= ':' . $prvicas[$a];
}
$koncniDatum = substr($koncniDatum, 1, strlen($koncniDatum));
if (strlen($koncniCas) > 0)
$koncniDatum .= ' ' . substr($koncniCas, 1, strlen($koncniCas));
$datum = $koncniDatum;
}
}
return $datum;
}
//translations:
//izbrani == selected
//datum == date
//cas == time
//koncni == end
//prvi == first
//drugi == second
With this, a user can enter date in the format "j.n.Y H:i" and also just portions of this format (j.n, n.Y, Y H:i,...).
I would like to thank Jon and nickb for help! link
Like many others I also struggled with this, well displaying the grid wasn't the problem, but filtering in the localized datetime was!
So I created my own formatter, used it in the search() function of my models (when passing the search parameters to compare()) and it works like a charm.
I can now filter on date/datetime fields in any localization (I use Dutch):
"30-12-2018" becomes "2018-12-30"
">30-12-2018" becomes ">2018-12-30"
"30-12-2018 23:59:49" becomes "2018-12-30 23:59:49"
">=30-12-2018 23:59:49" becomes ">=2018-12-30 23:59:49"
My localization:
// dateFormat['short'] = 'dd-MM-yyyy'
// timeFormat['medium'] = 'HH:mm:ss'
Yii::app()->format->datetimeFormat = strtr(Yii::app()->locale->dateTimeFormat,
array("{0}" => Yii::app()->locale->getTimeFormat('medium'),
"{1}" => Yii::app()->locale->getDateFormat('short')));
Yii::app()->format->dateFormat = 'short';
Yii::app()->format->timeFormat = 'medium';
My CGridView contains the following date time column:
'mutation_date_time:dateTime'
And (a snippet of) my own formatter with some handy functions:
class Formatter extends CLocalizedFormatter
{
public function formatWithoutSearchOperator($value)
{
// This snippet is taken from CDbCriteria->compare()
if(preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/',$value,$matches))
{
$value=$matches[2];
$op=$matches[1];
}
else
$op='';
return $value;
}
public function formatOnlySearchOperator($value)
{
// This snippet is taken from CDbCriteria->compare()
if(preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/',$value,$matches))
{
$value=$matches[2];
$op=$matches[1];
}
else
$op='';
return $op;
}
/*
* Format a localized datetime back to a database datetime (Y-m-d H:i:s).
* If a comparison operator is given, it is preserved. So strip it if you need to save the date in the database.
* If no time given, it's also not returned (MySQL database appends '00:00:00' as time to it upon saving).
* With this function the following localized datetimes just work like the stock datetime filters:
* - "30-12-2018" becomes "2018-12-30"
* - "30-12-2018 " becomes "1970-01-01" (note the extra space in input)
* - ">30-12-2018" becomes ">2018-12-30"
* - "30-12-2018 23:59:49" becomes "2018-12-30 23:59:49"
* - ">=30-12-2018 23:59:49" becomes ">=2018-12-30 23:59:49"
*
* For save() and afterFind() integration see:
* https://github.com/YetOpen/i18n-datetime-behavior
*/
public function formatToDatabaseDatetime($value)
{
// get the comparison operator from the string:
$comparator = $this->onlySearchOperator($value);
// get the datetime without the comparison operator:
$datetime = $this->withoutSearchOperator($value);
// parse the given datetime according to the locale format to a timestamp
$datetime_parsed = CDateTimeParser::parse(
$datetime,
strtr(
Yii::app()->locale->datetimeFormat,
array(
"{0}" => Yii::app()->locale->getTimeFormat(Yii::app()->format->timeFormat),
"{1}" => Yii::app()->locale->getDateFormat(Yii::app()->format->dateFormat)
)
)
);
// if its not a valid date AND time, check if it can be parsed to a date only:
if($datetime_parsed === false)
{
$date_parsed = CDateTimeParser::parse(
$datetime,
Yii::app()->locale->getDateFormat(Yii::app()->format->dateFormat)
);
}
// If no time part given, also output only the date
if($datetime_parsed===false)
{
$transformed = date(
'Y-m-d',
$date_parsed
);
}
else
{
$transformed = date(
'Y-m-d H:i:s',
$datetime_parsed
);
}
return $comparator . $transformed;
}
}
And within my search() function in my CActiveRecord model I use the following to compare the localized datetime with the records in the database:
$criteria->compare('mutation_date_time',Yii::app()->format->toDatabaseDateTime(trim($this->mutation_date_time)),true);
Please note the trim() there, that's by design (see function description formatToDatabaseDateTime()).
A big difference with filtering directly in correct database format: an invalid date converts to "1970-01-01"!
I highly appreciate feedback and I really hope my code helps somebody!

Getting precise column in Query result with Code Igniter

I am looking for a way to return the value of a precise column in the first result of a query.
The query result contains always 1 row containing the following columns :
ID
PW
RANK
I am trying to only get the rank value in order to push it into a session variable.
I tried messing with :
$row-> $query->row();
But then I don't know how to get only the value of the rank column. Ideally, I would want to get that value, then return it to allow my controller to set it in the session variable ( doing it in the model would be easier but would break the MVC pattern, right ?)
How can I do this ?
Thanks
Have the controller call a function in the model that return that value. Let's say the model has a function name get_rank()
public function get_rank($id)
{
// assumes your ID is an int
$id = (int)$id;
// avoid wasting a query
if ($id < 1) return FALSE;
// build query
$this->db->select('rank');
$this->db->from('YOUR_TABLE');
$this->db->where('id', $id);
// maybe some sorting / limiting here if you need it
// get result
$rs = $this->db->get();
if ($rs->num_rows() > 0)
{
// just get the first row
$row = $rs->row();
return $row->rank;
}
return FALSE;
}

NHibernate: Add criteria if param not null

I'm trying to retrieve a list of orders based on parameters specified by a user (basic search functionality). The user will enter either an orderId or a bunch of other params, those will get wrapped up into a message, and eventually make their way to the method below. My question is, how do I only look at the parameters that actually have values? So if a user were to enter a received date range and a store number and all other fields were null, I want to return orders for stores received in the date range and ignore all the null parameters. At first I was thinking I could use a conjunction, but I can't see a way to ignore the null parameters. Then I started splitting things out into the if statements below the main expression, but I don't want to look at those criteria if the user provides an externalId. Is there a simple way to do this?
public IList<Core.Order> GetOrderByCriteria
(
string ExternalId,
int? Store,
int? Status,
DateTime? beforeTransmissionDate, DateTime? afterTransmissionDate,
DateTime? beforeAllocationProcessDate, DateTime? afterAllocationProcessDate,
DateTime? beforeReceivedDate, DateTime? afterReceivedDate
)
{
try
{
NHibernate.ICriteria criteria = NHibernateSession.CreateCriteria(typeof(Core.Order))
.Add(Expression.Or
(
Expression.Like("ExternalId", ExternalId),
Expression.Conjunction()
.Add(Expression.Between("ReceivedDate", beforeReceivedDate, afterReceivedDate))
.Add(Expression.Between("TransmissionDate", beforeTransmissionDate, afterTransmissionDate))
.Add(Expression.Between("AllocationProcessDate", beforeAllocationProcessDate, afterAllocationProcessDate))
)
);
if(Store.HasValue)
criteria.Add(Expression.Eq("Status", Status));
if(Status.HasValue)
criteria.Add(Expression.Eq("Store", Store));
return criteria.List<Core.Order>();
}
catch (NHibernate.HibernateException he)
{
DataAccessException dae = new DataAccessException("NHibernate Exception", he);
throw dae;
}
}
I wound up dropping the whole conjunction thing and replacing the code in the try block with the code below. I also used joins which reduced the number of db accesses and reduced the amount of code needed.
NHibernate.ICriteria criteria = NHibernateSession.CreateCriteria(typeof(Core.Order));
if (!String.IsNullOrEmpty(ExternalId))
{
criteria.Add(Expression.Like("ExternalId", ExternalId));
}
if (beforeReceivedDate != null && afterReceivedDate != null)
criteria.Add(Expression.Between("ReceivedDate", beforeReceivedDate, afterReceivedDate));
if (beforeTransmissionDate != null && afterTransmissionDate != null)
criteria.Add(Expression.Between("TransmissionDate", beforeTransmissionDate, afterTransmissionDate));
if (beforeAllocationProcessDate != null && afterAllocationProcessDate != null)
criteria.Add(Expression.Between("AllocationProcessDate", beforeAllocationProcessDate, afterAllocationProcessDate));
if (Store.HasValue)
criteria.CreateCriteria("Store", "Store").Add(Expression.Eq("Store.LocationNumber", Store.Value));
return criteria.List<Core.Order>();
I had to do something similar not long ago. I'm pretty sure you can modify this to fit your needs.
private ICriteria AddSearchCriteria(ICriteria criteria, string fieldName, string value)
{
if (string.IsNullOrEmpty(fieldName))
return criteria;
if(string.IsNullOrEmpty(value))
return criteria;
criteria.Add(Expression.Like(fieldName, "%" + value + "%"));
return criteria;
}
The code calling the method ended up looking like this:
var query = session.CreateCriteria(typeof (User));
AddSearchCriteria(query, "FirstName", form["FirstName"]);
AddSearchCriteria(query, "LastName", form["LastName"]);
var resultList = new List<User>();
query.List(resultList);
return resultList;
Leave it up to the function to determine if the input is valid and whether to return the unmodified ICriteria or to add another Expression before returning it.