New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional Testing Collection Form Fields #4124

Closed
gzankevich opened this Issue Apr 26, 2012 · 24 comments

Comments

Projects
None yet
@gzankevich

gzankevich commented Apr 26, 2012

With form collections, we use Javascript to add the new fields and Symfony handles the rest.

In the following example, Office has a many-to-many with Contact.

When attempting the same approach in functional tests, e.g. by doing:

    $form = $buttonCrawlerNode->form(array(
            'company_whateverbundle_officetype[office_contacts][0][contact]' => '1'
    ));

The actual result is:

InvalidArgumentException: The form field "company_whateverbundle_officetype[office_contacts][0][contact]" does not exist.

The expected result is that a new contact is added.

Steps to reproduce:

  1. Create a couple of entities with a many-to-many association between them.
  2. Create a form with a collection field to edit the associations.
  3. Create a functional test and try to create a new association with it.
@gzankevich

This comment has been minimized.

gzankevich commented Apr 26, 2012

Same deal with collections of "file" entities when calling:

$form['company_whateverbundle_officetype[image_attachment][0][file]']->upload(__DIR__.'/../../Fixtures/SampleImage.png');
@stof

This comment has been minimized.

Member

stof commented Apr 26, 2012

Are you setting the allow_add option to true for the CollectionType ?

@gzankevich

This comment has been minimized.

gzankevich commented Apr 26, 2012

Yes, it works fine in dev/prod environments.

@leftdevel

This comment has been minimized.

leftdevel commented Jul 13, 2012

Hi @gzankevich, did you managed it?

@gzankevich

This comment has been minimized.

gzankevich commented Jul 16, 2012

Issue still persists. I'll try it out on a clean installation and see what happens.

@r4cker

This comment has been minimized.

r4cker commented Jul 24, 2012

I am facing the same problem.

  • Works fine in dev/prod
  • allow_add set to TRUE

@gzankevich Did you find what happend?

@gzankevich

This comment has been minimized.

gzankevich commented Jul 28, 2012

I've created a Gist containing all of the code necessary to reproduce the problem: https://gist.github.com/3193910

@carlescliment

This comment has been minimized.

carlescliment commented Nov 8, 2012

Subscribing.

I'll try submitting the form with a $client->request('POST', $data).

Not optimal, but it should at least let me test the controller.

@sstok

This comment has been minimized.

Contributor

sstok commented Feb 7, 2013

I was facing this problem to today, I actually needed to remove a row from the collection 😄

But found I little trick to make this work.

$form = $crawler->selectButton('save')->form();
$form->setValues(array(
    'customer_invoice_form[customer]' => 'C0001',
    'customer_invoice_form[address]'  => "274 Rose avenue US\n212-35 OKMontgomery",

    'customer_invoice_form[items][0][number]'        => 1,
    'customer_invoice_form[items][0][label]'         => 'Domainreg bar-foo.com',
    'customer_invoice_form[items][0][period][start]' => '01-01-2013',
    'customer_invoice_form[items][0][period][end]'   => '01-12-2013',
    'customer_invoice_form[items][0][price]'         => '20,00',
    'customer_invoice_form[items][0][taxPercent]'    => '21,10',
));

// Now do what ever you want with the $values.
$values = $form->getPhpValues();
unset($values['customer_invoice_form']['items'][1]);

$client->request($form->getMethod(), $form->getUri(), $values, $form->getPhpFiles());
//$client->submit($form);
@ste93cry

This comment has been minimized.

ste93cry commented Mar 14, 2013

I have the same problem: I'm using knockout to render a form client-side with javascript instead of rendering it with twig, however I can't submit any form which has inputs that don't exist. The problem is clear: the inputs are rendered client-side, so when I try to use the crawler to get them and change their values obviously it can't find them. There should be a way in the Symfony testing framework to submit data that isn't part of the form

@sstok

This comment has been minimized.

Contributor

sstok commented Mar 15, 2013

@ste93cry Try my method ;)

@leftdevel

This comment has been minimized.

leftdevel commented Mar 15, 2013

+1 @sstok. That is the way to go in phpunit.

@fnagel

This comment has been minimized.

Contributor

fnagel commented Feb 20, 2014

@sstok Is your workaround supposed to work in Symfony 2.3.x?

@fnagel

This comment has been minimized.

Contributor

fnagel commented Feb 20, 2014

Ok, here's another workaround:

$form = $crawler->filter('form .submit-button .btn-primary')->form();
$formData = array(
    'step2Type[positions][0][property1]' => '1',
    'step2Type[positions][0][property2]' => 'xyz',
);

$this->client->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $form->getPhpFiles(), array(), http_build_query($formData))
@gagarine

This comment has been minimized.

gagarine commented Jul 20, 2014

I have field than as formed with the name like
properties[0].value
properties[1].value

And no workarounds works.
I can't change the field name has it's on a service I don't control...

@wouterj

This comment has been minimized.

Member

wouterj commented Aug 11, 2014

This seems more like a mailinglist item than a bug/feature report afaics.

@jakzal

This comment has been minimized.

Member

jakzal commented May 12, 2015

re #3824

@placid2000

This comment has been minimized.

placid2000 commented Jul 23, 2015

I've faced the same a few times now and ignored it ill now.. Still no solution there? The workarounds don't seem to work for me neither

@sstok

This comment has been minimized.

Contributor

sstok commented Jul 23, 2015

properties[0].value
properties[1].value

Are property-paths, a property-path cannot be used for the DOMCrawler.

fnagel's solution works as it doesn't actually use the DOMCrawler but creates the request directly instead.

@alexislefebvre

This comment has been minimized.

Contributor

alexislefebvre commented Mar 8, 2016

(moved to #3824 (comment))

@webmozart webmozart removed the Form label Mar 9, 2016

@webmozart webmozart changed the title from [Form] Functional Testing Collection Form Fields to Functional Testing Collection Form Fields Mar 9, 2016

@fabpot

This comment has been minimized.

Member

fabpot commented Sep 21, 2018

Closing as the pull request was closed in favor of some documentation in symfony/symfony-docs#6427

@fabpot fabpot closed this Sep 21, 2018

@lordelph

This comment has been minimized.

lordelph commented Oct 14, 2018

I've got an alternative approach which perhaps better mirrors what really happens - before obtaining the Symfony\Component\DomCrawler\Form modify the retrieved DOM to insert dynamically created form fields. Here's a helper function which illustrates the approach

    protected function addFormField(Crawler $crawler, $formName, $inputName, $inputType='text')
    {
        //create input element in same document
        $doc = $crawler->getNode(0)->ownerDocument;
        $input=$doc->createElement('input');
        $input->setAttribute('type', $inputType);
        $input->setAttribute('name', $inputName);

        //add input to form
        $formNode=$crawler->filter('form[name="'.$formName.'"]')->getNode(0);
        $formNode->appendChild($input);
    }

Then a functional test just needs to add any dynamic form elements it needs before calling form()

//add a dynamic collection field for a file upload
$this->addFormField($crawler, 'my_entity', 'my_entity[images][0][newImage]', 'file');

//get the form as normal
$form = $crawler->selectButton('Update')->form();

//this will now work!
$form['product_type[images][0][newImage]']->upload($filename);
@alexislefebvre

This comment has been minimized.

Contributor

alexislefebvre commented Oct 20, 2018

@lordelph This is interesting, you could add it in the documentation as an alternative way to do the same thing as in symfony/symfony-docs#6427

lordelph added a commit to lordelph/symfony-docs that referenced this issue Oct 20, 2018

Alternative method for testing forms with collections
In response to suggestion in symfony/symfony#4124 (comment) this PR adds an alternative approach for testing forms which have dynamic collections. The suggestion is to manipulate the DOM before retrieving the Form object in a functional test.

lordelph added a commit to lordelph/symfony-docs that referenced this issue Oct 20, 2018

@lordelph

This comment has been minimized.

lordelph commented Oct 20, 2018

Added a PR here symfony/symfony-docs#10527

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment