How to test inner arrays with phpunit - phpunit

I have to test an array with inner arrays.
my array looks like the following.
$testdata=Array
(
[0] => Array
(
[label] => 'Ammy'
[idr] => 'user7'
[rel] => 7
)
[1] => Array
(
[label] => 'sidh'
[idr] => user8
[rel] => 8
)
[2] => Array
(
[label] => 'Alan'
[idr] => 'user9'
[rel] => 9
)
)
in this case my requirement is to assert whether the keys for inner array present using assertArrayHasKey() assertion of phpunit. I tried to do it like this
foreach ($testdata as $values) {
//print_r($values);
$this->assertArrayHasKey('idr', $values);
$this->assertArrayHasKey('rel', $values);
}
but this is not working for me. even the control does not go inside the foreach() loop.
please suggest me some solution for this.

foreach ($testdata as $values) {
//print_r($values);
$this->assertArrayHasKey('idr', $values);
$this->assertArrayHasKey('rel', $values);
}
this part in my question works fine. actually i was not getting the array itself in the test scenario. so it was not going inside the foreach(). now it is solved. i had a mistake in passing args to the function.

This is the example usage
/** Example One */
$testData = [
[
'label' => '',
'idr' => ''
], [
'label' => '',
'idr' => ''
], [
'label' => '',
'idr' => ''
]
];
$this->assertArrayStructure([
['label','idr']
], $testData);
/** Example Two */
$testData = [
'result' => true,
'data' => [
'col_1' => '',
'col_2' => ''
],
];
$this->assertArrayStructure([
'result', 'data' => ['col_1', 'col_2']
], $testData);
/** Example Three */
$testData = [
'result' => true,
'data' => [
[
'col_1' => '',
'col_2' => ''
],
[
'col_1' => '',
'col_2' => ''
]
],
];
$this->assertArrayStructure([
'result', 'data' => ['col_1', 'col_2']
], $testData, true);
Here is function
/**
* Like as assertJsonStructure
*
* #param array $data
* #param array $structures #e.g., [ key_1, key_2 => [child_key]]
* #param bool $dataHasMultiArray #e.g., $data[0][key]
*/
protected function assertArrayStructure(array $structures, array $data, bool $dataHasMultiArray = false)
{
$i = 0;
foreach ($structures as $index => $key) {
if (!is_numeric($index)) {
$this->assertArrayHasKey($index, $data);
}
if (is_string($key)) {
$this->assertArrayHasKey($key, $data);
}
if (is_array($key)) {
$this->assertArrayHasKeys($key, $dataHasMultiArray ? $data[$index][$i] : $data[$index]);
$i++;
}
}
}
/**
* #param $structures
* #param array $data
*/
protected function assertArrayHasKeys($structures, array $data)
{
foreach ($structures as $key) {
$this->assertArrayHasKey($key, $data);
}
}

You can also use
assertArraySubset()
from: https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertArraySubset
another solution is to compare arrays and then check if true:
$arrays_are_equal = ($array1 == $array2); // or === if you want identical
$this->assertTrue($arrays_are_equal);

Another option is to test only the first element of the multidimensional Array, like this:
$this->assertArrayHasKey('idr', $testdata[0]);
$this->assertArrayHasKey('rel', $testdata[0]);

I believe that that control is not going inside the foreach loop.
Remove whole :
$testdata= Array
(
[0] => Array
(
[label] => 'Ammy'
[idr] => 'user7'
[rel] => 7
)
[1] => Array
(
[label] => 'sidh'
[idr] => user8
[rel] => 8
)
[2] => Array
(
[label] => 'Alan'
[idr] => 'user9'
[rel] => 9
)
)

Related

symfony test undefined function

i have problem with my test. I don't know why my function is undefined. I add use statetment, phpstorm see this class. But when run test error with undefined.
namespace tests\AppBundle\Parser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use AppBundle\Parser\CommissionDataParser;
class CommissionDataParserTest extends WebTestCase
{
public function testGroupOrdersByWeek()
{
$orders = [
0 => [
'date' => '2016-01-10',
'client_id' => '2',
'client_type'=> 'natural',
'operation_type' => 'cash_in',
'operation_sum' => '200.00',
'operation_currency' => 'EUR',
],
1 => [
'date' => '2016-01-05',
'client_id' => '1',
'client_type'=> 'legal',
'operation_type' => 'cash_out',
'operation_sum' => '300.00',
'operation_currency' => 'EUR',
],
2 => [
'date' => '2016-01-11',
'client_id' => '1',
'client_type'=> 'natural',
'operation_type' => 'cash_out',
'operation_sum' => '30000',
'operation_currency' => 'JPY'
]
];
$expected = [
0 => [
'date' => '2016-01-05',
'client_id' => '2',
'client_type'=> 'natural',
'operation_type' => 'cash_in',
'operation_sum' => '200.00',
'operation_currency' => 'EUR',
],
1 => [
'date' => '2016-01-10',
'client_id' => '1',
'client_type'=> 'legal',
'operation_type' => 'cash_out',
'operation_sum' => '300.00',
'operation_currency' => 'EUR',
],
2 => [
'date' => '2016-01-11',
'client_id' => '1',
'client_type'=> 'natural',
'operation_type' => 'cash_out',
'operation_sum' => '30000',
'operation_currency' => 'JPY'
]
];
$um = new CommissionDataParser();
$result = $um->groupOrdersByWeek($orders);
$this->assertEquals($expected, $result, '**** -->>>>> result array wrong');
}
there is function that i want to test: i put small part of this class, for example
namespace AppBundle\Parser;
class CommissionDataParser
{
public function getData($file)
{
$orders = $this->extractOrders($file);
if (is_array($orders)) {
$orders = $this->groupOrdersByWeek($orders);
}
// ...
}
public function extractOrders($file)
{
$orders = [];
$data = [];
//$lines = explode(PHP_EOL, file_get_contents($file));
if (($handle = fopen($file, "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($row);
if ($num !== 6) {
return 'Badly structured file';
} else if ($num == 0) {
return 'file is empty';
}
$data[] = $row;
}
fclose($handle);
}
foreach ($data as $row)
{
$orders[] = [
'date' => $row[0],
'client_id' => $row[1],
'client_type' => $row[2],
'operation_type' => $row[3],
'operation_sum' => $row[4],
'operation_currency' => $row[5]
];
}
return $orders;
}
In first, you must check that your phpunit uses app/autoload.php as bootstrap. Open your phpunit.xml.dist file in your project root, and find this line:
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="app/autoload.php"
>
If u see this line bootstrap="app/autoload.php" in your file, then all right.
Next, check that your file CommissionDataParser.php physically located in this directory AppBundle\Parser. Full path to this file must be YOUR_PROJECT_ROOT\src\AppBundle\Parser\CommissionDataParser.php
If you did everything correctly then it should work. At least I was able to run your code.
yes really have :) i take a picture for example : )

Send choice Value instead choice key from Symfony form

I need to send from Symfony form ChoiceType::class
But I don't need choices keys, I need to send choices values.
Is that is possible?
$form->add('section', ChoiceType::class, array(
'mapped' => false,
'choices' => array(
1 => 'value1',
2 => 'value2'
),
));
I just want to send value1 if I chose value1,
not key 1 as default.
You can use
array_flip ($array)
refer to php docs
[Since Symfony 2.7] In any case you can play with choice value through choice_value option and a Closure function (Reference):
$form->add('section', ChoiceType::class, array(
'choice_value' => function ($value, $key, $index) {
return $value;
}
));
Useful for dynamic choices.
You just need to reverse it. Also, I don't think you need 'mapped'.
Try this:
$form->add(
'section',
ChoiceType::class,
[
'choices' => [
'value1' => 1,
'value2' => 2,
],
]
);
It should work.
Mayby a bit late but i've made this and it works perfect. Without array_flip. Mayby for someone it 'll be usefull.
$dataUsers = [];
$users = [
['id' => 1, 'firstname' => 'joe', 'lastname' => 'doe'],
['id' => 2, 'firstname' => 'will', 'lastname' => 'fog'],
];
foreach ($users as $u) {
$dataUsers[] = (object)['id' => $u['id'], 'label' => $u['firstname']];
}
$builder
->add('users', ChoiceType::class, [
'choices' => $dataUsers,
'choice_label' => function ($value) {
if (is_object($value)) {
return $value->label;
} else {
return 0;
}
},
'choice_value' => function ($value) {
if (is_object($value)) {
return $value->id;
} else {
return 0;
}
},
'data' => (object)[ 'id' => 2]
]);

MoneyField isChanged always returning true

I have a DataObject Confirmation that looks like this:
<?php
class Confirmation extends DataObject
{
private static $db = array(
'Reimbursement' => 'Money',
'SomeText' => 'Varchar(255)'
);
private static $has_one = array(
'Page' => 'Page'
);
public function getCMSFields()
{
$fields = parent::getCMSFields();
$reimbursementField = MoneyField::create('Reimbursement');
$someTextField = TextField::create('SomeText');
$reimbursementField->setAllowedCurrencies(array('SEK'));
$fields->addFieldsToTab(
'Root.Main',
array(
$reimbursementField,
$someTextField
)
);
return $fields;
}
public function onBeforeWrite()
{
parent::onBeforeWrite();
if($this->isChanged('Reimbursement')) SS_Log::log( print_r ( 'changed', true ), SS_Log::WARN );
}
}
if($this->isChanged('Reimbursement')) in the onBeforeWrite() function will always evaluate to true. Regardless of what is being changed. Even when saving without making any changes - it will fire the log function.
Edit: Checking the stacktrace with SS_Backtrace::backtrace() in Money.php's setValue() function I find that every time I save the Confirmation DataObject, setValue() is called without passing the $markChanged parameter set to false, from DataObject.php line 1281, resulting in the $isChanged flag being set to true, and the field always behaving as if it has changed.
When logging DataObject's getChangedFields() function I get the output below (when saving without making any changes). Notice the Reimbursement field being present, and before being empty. What am I missing here?
[22-Mar-2016 16:28:07] Warning at framework/model/DataObject.php line 2597: Array
(
[Reimbursement] => Array
(
[before] =>
[after] => Money Object
(
[currency:protected] => SEK
[amount:protected] => 25000
[isChanged:protected] => 1
[locale:protected] =>
[currencyLib:protected] => Zend_Currency Object
(
[_options:protected] => Array
(
[position] => 8
[script] =>
[format] =>
[display] => 2
[precision] => 2
[name] => svensk krona
[currency] => SEK
[symbol] => kr
[locale] => sv_SE
[value] => 0
[service] =>
[tag] => Zend_Locale
)
)
[allowedCurrencies:protected] =>
[value:protected] =>
[tableName:protected] =>
[name:protected] => Reimbursement
[arrayValue:protected] =>
[defaultVal:protected] =>
[failover:protected] =>
[customisedObject:protected] =>
[objCache:ViewableData:private] => Array
(
)
[class] => Money
[extension_instances:protected] => Array
(
)
[beforeExtendCallbacks:protected] => Array
(
)
[afterExtendCallbacks:protected] => Array
(
)
)
[level] => 2
)
)

Laravel ErrorException Undefined offset: 0

I am facing this error in laravel 5.
Here is the controller function in which I am facing the error (in the line where I do ($vendor->client[0]->id) :
public function show($username) {
Log::info('Vendors Controller : show function with '.$username);
$vendor = VendorProfile::where('username', $username)->first();
$output = print_r($vendor,1);
Log::info($output);
if($vendor) {
Log::info('client '. $vendor->client);
$client = Client::find($vendor->client[0]->id);
$title = $client->profile->company_name;
$output is printed as:
[2015-06-15 21:34:43] local.INFO: App\models\VendorProfile Object
(
[table:protected] => vendor_profile
[guarded:protected] => Array
(
[0] => id
)
[morphClass:protected] => MorphVendorProfile
[connection:protected] =>
[primaryKey:protected] => id
[perPage:protected] => 15
[incrementing] => 1
[timestamps] => 1
[attributes:protected] => Array
(
[id] => 16
[first_name] => some name
[last_name] =>
[company_name] => some name
[contact_number] => 1234567890
[username] => username
[profile_photo] =>
[photo_mime_type] =>
[cover_photo] =>
[cover_photo_mime_type] =>
[address] =>
[city_id] => 1
[zip_code] =>
[story] =>
[establishment_date] =>
[pricing] =>
[education] =>
[services_offered] =>
[assignments_undertook] =>
[advanced_fees] =>
[equipments] =>
[about_service] =>
[coins] => 500
[created_at] => 2015-06-15 20:21:45
[updated_at] => 2015-06-15 20:21:45
)
[original:protected] => Array
(
[id] => 16
[first_name] => some name
[last_name] =>
[company_name] => some name
[contact_number] => 1234567890
[username] => username
[profile_photo] =>
[photo_mime_type] =>
[cover_photo] =>
[cover_photo_mime_type] =>
[address] =>
[city_id] => 1
[zip_code] =>
[story] =>
[establishment_date] =>
[pricing] =>
[education] =>
[services_offered] =>
[assignments_undertook] =>
[advanced_fees] =>
[equipments] =>
[about_service] =>
[coins] => 500
[created_at] => 2015-06-15 20:21:45
[updated_at] => 2015-06-15 20:21:45
)
[relations:protected] => Array
(
)
[hidden:protected] => Array
(
)
[visible:protected] => Array
(
)
[appends:protected] => Array
(
)
[fillable:protected] => Array
(
)
[dates:protected] => Array
(
)
[casts:protected] => Array
(
)
[touches:protected] => Array
(
)
[observables:protected] => Array
(
)
[with:protected] => Array
(
)
[exists] => 1
)
The models VendorProfile and Client are connected as:
in VendorProfile model:
protected $morphClass = 'MorphVendorProfile';
// Defining 'Polymorphic' Relationship with Client Model
public function client() {
return $this->morphMany('App\models\Client', 'profile');
}
and I have an alias in my config/app.php:
'MorphVendorProfile'=> 'App\models\VendorProfile'
in Client model :
public function profile() {
return $this->morphTo();
}
Update:
This error has occurred while migrating the code from laravel 4.2 to laravel 5. So right now, when I run the previous code that was based on 4.2 version with the SAME database, and it didn't throw me any error, so I think problem is with the code, not database. I am certain that there is a problem with 'morph' relationships, I had to modify a bit in the process of migrating to make it work on other pages.
here is the morphTo function in my Eloquent/Model.php:
/**
* Define a polymorphic, inverse one-to-one or many relationship.
*
* #param string $name
* #param string $type
* #param string $id
* #return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function morphTo($name = null, $type = null, $id = null)
{
// If no name is provided, we will use the backtrace to get the function name
// since that is most likely the name of the polymorphic interface. We can
// use that to get both the class and foreign key that will be utilized.
if (is_null($name))
{
list(, $caller) = debug_backtrace(false, 2);
$name = snake_case($caller['function']);
}
list($type, $id) = $this->getMorphs($name, $type, $id);
// If the type value is null it is probably safe to assume we're eager loading
// the relationship. When that is the case we will pass in a dummy query as
// there are multiple types in the morph and we can't use single queries.
if (is_null($class = $this->$type))
{
Log::info('eagerly loading');
return new MorphTo(
$this->newQuery(), $this, $id, null, $type, $name
);
}
// If we are not eager loading the relationship we will essentially treat this
// as a belongs-to style relationship since morph-to extends that class and
// we will pass in the appropriate values so that it behaves as expected.
else
{
Log::info('not eagerly loading');
Log::info($class);
$instance = \App::make('\App\models\\'.$class);
$output = print_r($instance,1);
Log::info('*'.$output.'*');
return new MorphTo(
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
);
}
}
Check your namespaces. Make sure that the polymorphic relationship that you have setup references the full namespace in both the Vendor and Client models

trouble with update_option() in WordPress import settings function

I am having a bit of trouble with an import/export option I'm building into my theme. Hopefully I explain this well, let me start with the function.
function ifeature_import_options() {
$options = get_option('ifeature');
$import = $options['if_import_code'];
if ($import != '');
$options_array = (unserialize($import));
foreach( $options_array as $option_name => $option_value ) {
update_option( $option_name, $option_value );
}
}
if_import_code returns the serialized output of $options (which the user enters into a textarea in my options panel), and I've tested that $options_array is properly unserializing the import code as it prints the following:
Array ( [if_menu_color] => Pink [if_font] => Arial [if_css_options] =>
[if_favicon] => [if_ga_code] => [if_import_code] => [if_export_code]
=> b:0; [if_logo] => [if_menuicon] => [if_header_contact] =>
[if_facebook] => [if_twitter] => [if_linkedin] => [if_youtube] =>
[if_googlemaps] => [if_email] => [if_rsslink] => [if_home_description]
=> [if_home_keywords] => [if_home_title] => [if_callout_title] =>
[if_callout_text] => [if_callout_img] => [if_callout_image_link] =>
[if_slider_type] => posts [if_slider_placement] => feature
[if_slider_category] => [if_slider_posts_number] => [if_slider_height]
=> [if_slider_delay] => [if_slider_animation] => random
[if_footer_text] => [if_hide_callout] => 0 [if_show_fb_like] => 0
[if_hide_slider] => 0 [if_hide_boxes] => 0 [if_hide_link] => 0
[if_slider_navigation] => 0 )
So I have the new array that needs to be written to my options, but the update_options code I've used isn't working. What am I missing?
$options_array = unserialize($importOptions);
foreach ($options_array as $option_name=>$value) {
if ($value != '') update_option( $key, $value );
}

Resources