I'm new with PhpUnit, and I have some doubts on best practices writing tests.
My first test is as following:
<?php
require_once '../Scrap.php';
class ScrapTest extends PHPUnit_Framework_TestCase
{
protected $scrap;
// Setup function to instantiate de object to $this->scrap
protected function setUp()
{
$this->scrap = new Scrap;
}
/**
* #covers Scrap::getPhone
*
*/
public function testGetPhone() {
// Variables
$array_static1 = Array(0 => 218559372, 1 => 927555929, 2 => 213456789, 3 => 912345678);
$phone_list1 = '</div>A Front para<br /><br /><br /><br /><br /><br />-Apoio;<br />-Criação;<br />-Campanhas;<br />-Promoções<br /><br /><br />CONDIÇÕES:<br /><br />Local de Trabalho: Es<br />Folgas: Mistas<br /><br /><br /><br />ordem 500€<br /><br /><br /><br />Mínimos:<br /><br />- Conhecimentos;<br />- Ensino ;<br />-INGLÊS.<br /><br /><br /><br />Candidaturas: <br />email#ffff.es<br />218559372 | 927 555 929 | <br />RH<br />Rua C. Sal. 40<br />1000-000 Lisboa<br /><br /><br />+351 21 3456789 | (351) 912345678';
$this->assertEquals($array_static1, $this->scrap->getPhone($phone_list1, '351', '9'));
}
}
?>
Can I do beter than this? Is this the correct way of doing it?
If you can give me some clues I would be appreciated.
Best Regards,
I would use dataProvider feature of phpUnit in this case. That will allow you to have simple, clean test case and additional method with different test data sets.
Example:
public function getTextsAndPhones() {
return array(
array(
'</div>A Front para<br /><br />(...)<br />+351 21 3456789 | (351) 912345678',
array(0 => 218559372, 1 => 927555929, 2 => 213456789, 3 => 912345678),
),
);
}
/**
* #dataProvider getTextsAndPhones
*/
public function testGetPhone( $text, $phones ) {
$this->assertEquals($phones, $this->scrap->getPhone($text, '351', '9'));
}
Of course you can include '351' and '9' parameters in the data provider as well.
I would load the fixture (the HTML that will be injected), from a file, using file_get_contents. It's a bit mess having a long HTML string.
Also, it's convenient having clear variable names. In your case, $array_static1 could be renamed to $expected_phone_numbers.
Related
I have an OROCRM application and there is a datagrid, needs to be extended with a column named by userNames, and intented to display data in a custom twig cell.
To maintain this i made a DataGridListener class and in it a method to extend columns:
/**
* Creates specific column names for selected persons
*
* #param Datagrid $datagrid
* #param array $persons
*
* #return array
*/
protected function addColumnsForPersons(Datagrid $datagrid, array $persons): array
{
$config = $datagrid->getConfig();
$additionalColumns = [];
foreach ($persons as $person) {
$column = [
'label' => $person->getName(),
'template' => 'MyBundle:Partials/Datagrid/Attendance:person_attendance.html.twig',
'type' => 'twig',
'frontend_type' => 'html',
'data_name' => 'person_' . $person->getId(),
'data' => 'person_' . $person->getId(),
'translatable' => false,
'editable' => false,
'align' => 'middle'
];
$config->addColumn('person_' . $person->getId(), $column);
$additionalColumns[] = 'person_' . $person->getId();
}
return $additionalColumns;
}
I add also data for person by the following:
$wrapperData = $datagrid->getData();
foreach($attendancesAtDay as $attendance) {
// This block can be changed to a workaround
$dayData['person_' . $attendance['personid']] = (object)([
'arrival' => Carbon::createFromFormat('Y-m-d G:i:s', $attendance['arrival'])->format('H:i'),
'leave' => Carbon::createFromFormat('Y-m-d G:i:s', $attendance['leave'])->format('H:i'),
'logins' => $attendance['logins'],
'worktime' => gmdate('H:i', $attendance['worktime'] * 60)
]);
}
$gridData[] = $dayData;
$wrapperData->setData($gridData);
The template is reachable and PHPStorm can follow its link from reference, and is the following:
<div>
<div style="width:40px">
{{ value.worktime }}
</div>
<div style="width:40px">
{{ value.arrival }}
</div>
<div style="width:40px">
{{ value.leave }}
</div>
<div style="width:40px">
{{ value.logins }}
</div>
</div>
With this method i got the columns named by person, but with empty data. With xdebug the code never goes into the template.
With some workaround if i change the block in the foreach it renders needed data.
The workaround is the following:
$dayData['person_' . $attendance['personid']] = sprintf(
'<table>
<tr>
<td>
Worktime
</td>
<td>
Arrival
</td>
<td>
Leave
</td>
<td>
Logins
</td>
</tr>
<tr>
<td>
%s
</td>
<td>
%s
</td>
<td>
%s
</td>
<td>
%s
</td>
</tr>
</table>',
gmdate('H:i', $attendance['worktime'] * 60),
Carbon::createFromFormat('Y-m-d G:i:s', $attendance['arrival'])->format('H:i'),
Carbon::createFromFormat('Y-m-d G:i:s', $attendance['leave'])->format('H:i'),
$attendance['logins']);
I tried to use array instead of object without success, or any error message in var/logs/dev.log .
I wanted to avoid this workaround, and wondering why don't throws error in case i added booth twig template to column and html code as data, and why doesn't runs into the cell template?
So what do i wrong?
Thanks for any help!
I load my image (blob data ) in my GETer Entity
When I just return ($this->foto) in my GETer I see :Resource id #284 on the screen
When I change my GETer like this : return stream_get_contents($this->foto);
I see these : ���JFIF��� ( ,,,,,,,, ( and more )
In my Controller a call the index.html.twig to show all my entities
/**
* Lists all Producten entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CustomCMSBundle:Producten')->findAll();
return $this->render('CustomCMSBundle:Producten:index.html.twig', array(
'entities' => $entities,
));
}
Now in my views ( index.html.twig ) I like to show the picture
{% for entity in entities %}
<tr>
<td>
<img src="{{ entity.foto}}" alt="" width="80" height="80" />
</td>
<td>
{{ entity.foto }}
</td>
<td>
<ul>
<li>
show
</li>
<li>
edit
</li>
</ul>
</td>
</tr>
{% endfor %}
But I don't see the picture ?
Can anyone help me?
You are using <img src="(raw image)"> instead of <img src="(image's url)">
A quick solution is to encode your image in base64 and embed it.
Controller
$images = array();
foreach ($entities as $key => $entity) {
$images[$key] = base64_encode(stream_get_contents($entity->getFoto()));
}
// ...
return $this->render('CustomCMSBundle:Producten:index.html.twig', array(
'entities' => $entities,
'images' => $images,
));
View
{% for key, entity in entities %}
{# ... #}
<img alt="Embedded Image" src="data:image/png;base64,{{ images[key] }}" />
{# ... #}
{% endfor %}
in your entity write your image getter like this:
public function getFoto()
{
return imagecreatefromstring($this->foto);
}
and use it instead of the object "foto" property.
php doc for the function: http://php.net/manual/de/function.imagecreatefromstring.php
A more direct way, without extra work in the controller:
In the Entity Class
/**
* #ORM\Column(name="photo", type="blob", nullable=true)
*/
private $photo;
private $rawPhoto;
public function displayPhoto()
{
if(null === $this->rawPhoto) {
$this->rawPhoto = "data:image/png;base64," . base64_encode(stream_get_contents($this->getPhoto()));
}
return $this->rawPhoto;
}
In the view
<img src="{{ entity.displayPhoto }}">
EDIT
Thanks to #b.enoit.be answer to my question here, I could improve this code so the image can be displayed more than once.
As it is said before you must use base64 method, but for a better performance and usability, the correct option is creating a custom twig filter (Twig extension) as described here .
<?php
namespace Your\Namespace;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class TwigExtensions extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('base64', [$this, 'twig_base64_filter']),
];
}
function twig_base64_filter($source)
{ if($source!=null) {
return base64_encode(stream_get_contents($source));
}
return '';
}
}
In your template:
<img src="data:image/png;base64,{{ entity.photo | base64 }}">
I am very new to angularJS and you can say that this is my first day using angularJS.
it seems silly BUt i am trying to do some basic stuff which is not working somehow.
I have a text box in which if you enter 1234, Count should be 555 OR if you enter any number it should be 550 and i am putting 1234 on page load so it is showing me 555 BUT when i change value in textbox, Count is not changing.
<div ng-app>
<div ng-controller="prCtrl">
Enter Product ID to get the reviews details
<input type="number" ng-model="productId" required />
<br />
Total Review Count = {{ Count }}
</div>
</div>
function prCtrl($scope,$http) {
$scope.productId = 1234;
if ($scope.productId === 1234) {
$scope.Count = 555;
} else {
$scope.Count = 550;
}
}
how can i change {{ Count }} depending on the value entered in textbox.
thanks
An option would be to subscribe to the model change and carry out your logic there:
Controller:
function prCtrl($scope,$http) {
$scope.productId = 1234;
$scope.$watch('productId', function(newValue, oldValue){
if (newValue === 1234) {
$scope.Count = 555;
} else {
$scope.Count = 550;
}
});
}
View:
<div ng-app>
<div ng-controller="prCtrl">
Enter Product ID to get the reviews details
<input type="number" ng-model="productId" required />
<br />
Total Review Count = {{ Count }}
</div>
</div>
I have tested that, and it appears to do what you want.
And a final note - you mention you are new to angular - I would highly recommend egghead.io 's sessions on AngularJS ( https://egghead.io/lessons ). They are good at getting you up to speed with AngularJS :)
Alternatively you can use a function, without watching the value using $watch
function prCtrl($scope,$http) {
$scope.productId = 1234;
$scope.getCount = function() {
if ($scope.productId === 1234) {
return 555;
} else {
return 550;
}
}
}
view:
<div ng-app>
<div ng-controller="prCtrl">
Enter Product ID to get the reviews details
<input type="number" ng-model="productId" required />
<br />
Total Review Count = {{ getCount() }} // replaced with function call
</div>
</div>
This function gets called when ever a model is changed in the scope, so it will always update your value
I'm having trouble writing a Symfony 2 functional test to set checkboxes that are part of an array (i.e. a multiple and expanded select widget)
In the documentation the example is
$form['registration[interests]']->select(array('symfony', 'cookies'));
But it doesn't show what html that will work with and it doesn't work with mine. Here is a cutdown version of my form
<form class="proxy" action="/proxy/13/update" method="post" >
<input type="checkbox" id="niwa_pictbundle_proxytype_chronologyControls_1" name="niwa_pictbundle_proxytype[chronologyControls][]" value="1" />
<input type="checkbox" id="niwa_pictbundle_proxytype_chronologyControls_2" name="niwa_pictbundle_proxytype[chronologyControls][]" value="2" />
<input type="checkbox" id="niwa_pictbundle_proxytype_chronologyControls_3" name="niwa_pictbundle_proxytype[chronologyControls][]" value="3" />
</form>
Once it get it working there I'm going to move on to a manually made form
<input type="checkbox" id="13" name="proxyIDs[]" value="13">
<input type="checkbox" id="14" name="proxyIDs[]" value="14">
<input type="checkbox" id="15" name="proxyIDs[]" value="15">
I have tried things like
$form = $crawler->selectButton('Save')->form();
$form['niwa_pictbundle_proxytype[chronologyControls]']->select(array('3'));
$form['niwa_pictbundle_proxytype[chronologyControls][]']->select(array('3'));
but the first fails saying select is being run on a non-object and the second says Unreachable field "".
Try
$form['niwa_pictbundle_proxytype[chronologyControls]'][0]->tick();
It indexes it from 0 even in the form it says []
Or if it doesn't really helps you, you can try POSTing an array directly to the action instead of using symfony's form selectors. See: Symfony2: Test on ArrayCollection gives "Unreachable field"
Hope one of them helps you.
I think the most bulletproof solution working in 2017 is to extend your test class:
/**
* Find checkbox
*
* #param \Symfony\Component\DomCrawler\Form $form
* #param string $name Field name without trailing '[]'
* #param string $value
*/
protected function findCheckbox($form, $name, $value)
{
foreach ($form->offsetGet($name) as $field) {
$available = $field->availableOptionValues();
if (strval($value) == reset($available)) {
return $field;
}
}
}
And in the test call:
$this->findCheckbox($form, 'niwa_pictbundle_proxytype[chronologyControls]', 3)->tick();
I have made an instance of the type competition by retrieving data from my database.
The function selectCompetitionById return one row of data.
Competition competition = BLLc.selectCompetitionById(competitionId);
How can I display item of this instance on my page? (Repeater doesn't work)
If you want to create an auto-generated form, then you could use a DetailsView:
<asp:DetailsView ID="competitionDetails" RunAt="Server" AutoGenerateColumns="true" />
Create a dummy array (with just the one item) as the data source:
competitionDetails.DataSource = new Competition[] { competition };
The other way is to use standard HTML template that references your object. Make it a property of the page first:
<script runat="Server">
public Competition competition { get; set; }
void Page_Load()
{
competition = BLLc.selectCompetitionById(competitionId);;
this.DataBind();
}
</script>
Then reference it in markup as needed:
<div>
<span>Title</span>
</div>
<div>
<span><%# competition.Title %></span>
</div>
<div> etc ... </div>