Symfony2: PHPUnit Testing-> #dataProvider sends no multipleArray - unit-testing

I make UnitTesting for my application.
I have a save saveArticleIds() Method and I wrote a testing for it -> testSaveArticelIds(). I have an dataProvider articelIdsArray() whith a multiple array. The function need that array exact like this.
/**
*
* #dataProvider articleIdsArray
*
*/
public function testSavearticleIds($articleIds) {
$articleIdObjekt = new ArticleIdHandler();
$result = $articleIdObjekt->saveArticleIds($articleIds,false);
$this->assertTrue($result);
}
public function articleIdsArray() {
return array(
array(
10552 => 10552,
14314 => 14314,
21034 => 21034,
22739 => 22739,
34568 => 34568,
34572 => 34572,
35401 => 35401,
38292 => 38292,
55141 => 55141,
161764 => 161764,
181589 => 181589
)
);
}
When I run my test, I get this Error:
There was 1 error: 1) My\Bundle\ArticleBundle\Tests\Article\ArticleIdHandlerTest::testSaveArticleIds
with data set #0 (10552, 14314, 21034, 22739, 34568, 34572, 35401, 38292, 55141, 161764, 181589)
Invalid argument supplied for foreach()
Why does it show the array like I have no keys in the array? I need the array exact like in my dataProvider! Any idea?? THANKS A LOT FOR YOU HELP!!!

maybe try this:
public function articleIdsArray()
{
return
array(
array(
array(
10552 => 10552,
14314 => 14314,
21034 => 21034,
22739 => 22739,
34568 => 34568,
34572 => 34572,
35401 => 35401,
38292 => 38292,
55141 => 55141,
161764 => 161764,
181589 => 181589
)
)
);
}
The reason is that the first level of the array nesting is the set of data provided for each round of tests, the second level represents the arguments provided to testSavearticleIds, in the same order as in the parameter list of the function (in your example there is only one argument), the last level is just the test array itself.
Hope this helps...

Try this :
/**
* #dataProvider articleIdsArray
*/
public function testSavearticleIds($articleIds)
{
$articleIdObjekt = new ArticleIdHandler();
$result = $articleIdObjekt->saveArticleIds($articleIds,false);
$this->assertTrue($result);
}
public function articleIdsArray()
{
return array(
'scenario_one' => 10552,
'scenario_two' => 14314,
...,
);
}

You doesn't need to use #dataProvider in your example.
Define your method like this
public function getArticleIdsArray() {
return array(
10552 => 10552,
14314 => 14314,
21034 => 21034,
22739 => 22739,
34568 => 34568,
34572 => 34572,
35401 => 35401,
38292 => 38292,
55141 => 55141,
161764 => 161764,
181589 => 181589
);
}
and use it in your test
public function testSavearticleIds($articleIds) {
$articleIdObjekt = new ArticleIdHandler();
$result = $articleIdObjekt->saveArticleIds($this->getArticleIdsArray(),false);
$this->assertTrue($result);
}

Related

Codeception/Doctrine2: Calling 'grabEntityFromRepository' before 'canSeeInRepository' causes the latter to break

An odd one. I'm testing a REST API using Codeception and Symfony4/Doctrine2.
If a test has a single call to $I->canSeeInRepository(...);, it works fine.
However, if I make a call to $I->grabEntityFromRepository(...); (which works fine) before making this call, the $I->canSeeInRepository(...); call fails.
It seems like some kind of Doctrine issue.
Can anybody shed some light? Many thanks.
/**
* #param ApiTester $I
*/
public function testConvertOfferToTemplate(ApiTester $I)
{
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
/** #var \App\ServiceProviderBundle\Entity\Offer $offer */
$offer = $I->grabEntityFromRepository(\App\ServiceProviderBundle\Entity\Offer::class, [
'notes' => 'SOME NOTES - Custom Offer final draft',
'dateArchived' => null,
]);
$I->sendPOST('/offer-templates', json_encode([
'name' => 'Codeception Created Template From Offer',
'offer_id' => $offer->getId(),
]));
$json = array(
'offer_template' =>
array(
'name' => 'Codeception Created Template From Offer',
'charge_period' => $offer->getChargePeriod(),
'charge_amount' => $offer->getChargeAmount(),
'charge_currency' => $offer->getChargeCurrency(),
'terms' => $offer->getTerms(),
'_embedded' =>
array(),
),
);
$I->seeResponseContainsJson($json);
$I->canSeeInRepository(\App\ServiceProviderBundle\Entity\OfferTemplate::class, [
'name' => 'Codeception Created Template From Offer', // FAILS
]);
}
/**
* #param ApiTester $I
*/
public function testOfferCreatedFromTemplate(ApiTester $I)
{
$I->canSeeInRepository(\App\ServiceProviderBundle\Entity\OfferTemplate::class, [
'name' => 'Codeception Created Template From Offer', // PASSES
]);
}

SF2: How to custom the form type messages?

I want to know how I can modify the error message on my ContactType.
It's possible directly in the Type ?
My current code:
class ContactType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$collectionConstraint = new Collection(array(
'name' => array(
new NotBlank(array('message' => 'My custon message.')),
new Length(array('min' => 2), array('message' => 'My custon message.'))
),
'email' => array(
new NotBlank(array('message' => 'My custon message.')),
new Email(array('message' => 'My custon message.'))
),
'subject' => array(
new NotBlank(array('message' => 'My custon message.')),
new Length(array('min' => 10), array('message' => 'My custon message.'))
),
'message' => array(
new NotBlank(array('message' => 'My custon message')),
new Length(array('min' => 5))
)
));
$resolver->setDefaults(array(
'constraints' => $collectionConstraint
));
}
public function getName()
{
return 'contact';
}
}
Thanks you all for your helping.
Best regards,
It's recommend to change the message of the assertion instead, but you can also use the invalid_message setting of a form type.

zend framework 2 Unable to render template resolver could not resolve to a file

I'm learning how to use Zend Framework2. According to some tutorials available on the Net I've wrote some pieces of code . The most important tutorial for me is this one: https://github.com/psamatt/zf2-doctrine-example It covers most of the basics that i've planned to write. I've stuck on one problem that looks strange to me. On my summary page, that display all the records from DB I have a links to add new record, edit existing record, and delete record. Routing is covered by module.config.php:
'router' => array(
'routes' => array(
'incident' => array(
'type' => 'segment',
'options' => array(
'route' => '/incident[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Helpdesk\Controller\Incident',
'action' => 'index',
),
),
),
),
),
When I use a link to a new record (h.t.t.p://helpdesk/incident/add) everything works correctly. But when I use a link to edit my record (h.t.t.p://helpdesk/incident/edit/1 - where 1 is example record ID) I receive an error:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "helpdesk/incident/edit"; resolver could not resolve to a file
This is my IncidentController.php:
<?php
namespace Helpdesk\Controller;
use Application\Controller\EntityUsingController;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use Doctrine\ORM\EntityManager;
use Zend\View\Model\ViewModel;
use Helpdesk\Form\IncidentForm;
use Helpdesk\Entity\Incident;
class IncidentController extends EntityUsingController
{
/**
* Index action
*
*/
public function indexAction()
{
$em = $this->getEntityManager();
$incidents = $em->getRepository('Helpdesk\Entity\Incident')->findAll();
return new ViewModel(array(
'incidents' => $incidents
));
}
/**
* Edit action
*
*/
public function editAction()
{
$incident = new Incident();
if ($this->params('id') > 0) {
$incident = $this->getEntityManager()->getRepository('Helpdesk\Entity\Incident')->find($this->params('id'));
}
$form = new IncidentForm($this->getEntityManager());
$form->bind($incident);
$form->setHydrator(new DoctrineObject($this->getEntityManager(),'Helpdesk\Entity\Incident'));
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($incident->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$em = $this->getEntityManager();
$em->persist($incident);
$em->flush();
$this->flashMessenger()->addSuccessMessage('Incident saved');
// Redirect to list of incidents
return $this->redirect()->toRoute('incident');
}
}
return array(
'incident' => $incident,
'form' => $form,
);
}
/**
* Add action
*
*/
public function addAction()
{
return $this->editAction();
}
/**
* Delete action
*
*/
public function deleteAction()
{
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('incident');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->post()->get('del', 'No');
if ($del == 'Yes') {
$id = (int)$request->post()->get('id');
$incident = $this->getEntityManager()->find('Helpdesk\Entity\Incident', $id);
if ($incident) {
$this->getEntityManager()->remove($incident);
$this->getEntityManager()->flush();
}
}
// Redirect to list of incidents
return $this->redirect()->toRoute('default', array(
'controller' => 'incident',
'action' => 'index',
));
}
return array(
'id' => $id,
'incident' => $this->getEntityManager()->find('Helpdesk\Entity\Incident', $id)->getArrayCopy()
);
}
}
What is the difference between these two? Why one works fine, while the second one generates an error?
Thanks for your help
Smok.
Most likely helpdesk/incident/edit.phtml does not exist, while add action is rendering an existing helpdesk/incident/add.phtml.
You can reuse the existing helpdesk/incident/add.phtml or create a new one.

Doctrine2 + Zend Framework 2 - EntitiesManager as variable in Controller

I want to set EntitiesManager instance available on my Controller. I want the Instance available with $this->em on Controller. This is my configuration :
module.config.php
[...]
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/Application/Entity')
),
'orm_default' => array(
'drivers' => array(
'Application\Entity' => 'application_entities'
),
),
),
),
'di' => array(
'instance' => array(
'alias' => array(
'application' => 'Application\Controller\IndexController',
),
'Application\Controller\IndexController' => array(
'parameters' => array(
'em' => 'doctrine_em',
),
),
),
),
IndexController.php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use \Doctrine\ORM\EntityManager;
class IndexController extends AbstractActionController
{
protected $em;
public function setEm(EntityManager $em) {
$this->em = $em;
return $this;
}
public function indexAction() {
$user1 = $this->em->find('\Application\Entity\User', 1);
var_dump($user1->getFullname());
}
I got this error : "Fatal error: Call to a member function find() on a non-object". It seem than EntityManager is not correctly instantiate.
What Am I missing?
Thank you!
You dont need anything in the module config
You edit the Module.php, onbootstrap function
public function onBootstrap(\Zend\EventManager\EventInterface $e) {
$serviceManager = $e->getApplication()->getServiceManager();
$em = $serviceManager;
$controllerLoader = $serviceManager->get('ControllerLoader');
$controllerLoader->addInitializer(function ($controller) use ($em) {
if (method_exists($controller, 'setEm')) {
$controller->setEm($em);
}
});
}
the controller stays as you have it, with the $em field, and the setEm method
//..
protected $em;
public function setEm(EntityManager $em) {
$this->em = $em;
return $this;
}
//..

Form collections in SF2

Offers.php
/**
* #var \ZGoffers\MainBundle\Entity\OfferParameter
*
* #ORM\OneToMany(targetEntity="OfferParameter", mappedBy="offer", cascade={"all"})
*/
private $parameters;
OfferParameter.php
/**
* #var \ZGoffers\MainBundle\Entity\Offer
*
* #ORM\ManyToOne(targetEntity="Offer", inversedBy="offer", cascade={"all"})
*/
private $offer;
OfferType.php
class OfferType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('advertiser')
->add('name')
->add('url', 'text', array('label' => 'URL'))
->add('externalUrl', 'text', array('label' => 'External URL'))
->add('dailyCap', 'text', array('label' => 'Daily Cap'))
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true
))
->add('active', 'choice', array(
'choices' => array(0 => 'Disabled', 1 => 'Enabled')
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\Offer'
);
}
}
OfferParameterType.php
class OfferParameterType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('field')
->add('type', 'choice', array(
'choices' => array(
'=' => 'EQUALS',
'>' => 'IS GREATER THAN',
'>=' => 'IS GREATER THAN OR EQUALS',
'<' => 'IS LESS THAN',
'<=' => 'IS GREATER THAN OR EQUALS'
)
))
->add('value');
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\OfferParameter'
);
}
}
Form Handling
public function process()
{
if ('POST' == $this->request->getMethod()) {
// bind form data
$this->form->bindRequest($this->request);
// If form is valid
if ($this->form->isValid() && ($offer = $this->form->getData()) instanceof Offer) {
foreach ($offer->getParameters() as $parameter) {
$parameter->setOffer($offer); // THIS SHOULDNT BE NEEDED
}
// save offer to the database
$this->entityManager->persist($offer);
$this->entityManager->flush();
return true;
}
}
return false;
}
My question is.... How the hell do you delete elements in form collections in SF2????
I have multiple forms that are just like this one in my project and it's really putting a halt to development :(
Thanks for all help!
You may need to do something like below :
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true,
'attr'=>array('style'=>'display:none;')
))
That makes your whole OfferParameterType collection hidden.
Or in OfferParameterType apply same thing for each field like below :
->add('field',null, array('attr'=>array('style'=>'display:none;')))