mautic / app /bundles /FormBundle /Tests /Controller /SubmissionFunctionalTest.php
chrisbryan17's picture
Upload folder using huggingface_hub
d2897cd verified
<?php
declare(strict_types=1);
namespace Mautic\FormBundle\Tests\Controller;
use Mautic\CampaignBundle\Entity\Campaign;
use Mautic\CampaignBundle\Entity\Lead;
use Mautic\CampaignBundle\Model\CampaignModel;
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
use Mautic\FormBundle\Entity\Submission;
use Mautic\FormBundle\Entity\SubmissionRepository;
use Mautic\UserBundle\Entity\Role;
use Mautic\UserBundle\Entity\RoleRepository;
use Mautic\UserBundle\Entity\User;
use Mautic\UserBundle\Entity\UserRepository;
use PHPUnit\Framework\Assert;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
final class SubmissionFunctionalTest extends MauticMysqlTestCase
{
protected $useCleanupRollback = false;
public function testRequiredConditionalFieldIfNotEmpty(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'fields' => [
[
'label' => 'Country',
'type' => 'country',
'alias' => 'country',
'leadField' => 'country',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
'formAttributes' => 'class="foobar"',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
// Add conditional state field dependent on the country field:
$patchPayload = [
'fields' => [
[
'label' => 'State',
'type' => 'select',
'alias' => 'state',
'leadField' => 'state',
'parent' => $response['form']['fields'][0]['id'],
'isRequired' => true,
'conditions' => [
'expr' => 'in',
'any' => 0,
'values' => ['Australia'],
],
'properties' => [
'syncList' => 1,
'multiple' => 0,
],
],
],
];
$this->client->request(Request::METHOD_PATCH, "/api/forms/{$formId}/edit", $patchPayload);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$this->assertStringContainsString(' class="foobar"', $crawler->html());
$form = $formCrawler->form();
$form->setValues([
'mauticform[country]' => 'Australia',
'mauticform[state]' => 'Victoria',
]);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
/** @var SubmissionRepository $submissionRepository */
$submissionRepository = $this->em->getRepository(Submission::class);
// Ensure the submission was created properly.
$submissions = $submissionRepository->findBy(['form' => $formId]);
Assert::assertCount(1, $submissions);
/** @var Submission $submission */
$submission = $submissions[0];
Assert::assertSame([
'country' => 'Australia',
'state' => 'Victoria',
], $submission->getResults());
// A contact should be created by the submission.
$contact = $submission->getLead();
Assert::assertSame('Australia', $contact->getCountry());
Assert::assertSame('Victoria', $contact->getState());
// The previous request changes user to anonymous. We have to configure API again.
$this->setUpSymfony($this->configParams);
// Cleanup:
$this->client->request(Request::METHOD_DELETE, "/api/forms/{$formId}/delete");
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
}
public function testRequiredConditionalFieldIfAllFieldsEmpty(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'fields' => [
[
'label' => 'Country',
'type' => 'country',
'alias' => 'country',
'leadField' => 'country',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Add conditional state field dependent on the country field:
$patchPayload = [
'fields' => [
[
'label' => 'State',
'type' => 'select',
'alias' => 'state',
'leadField' => 'state',
'parent' => $response['form']['fields'][0]['id'],
'isRequired' => true,
'conditions' => [
'expr' => 'in',
'any' => 0,
'values' => ['Australia'],
],
'properties' => [
'syncList' => 1,
'multiple' => 0,
],
],
],
];
$this->client->request(Request::METHOD_PATCH, "/api/forms/{$formId}/edit", $patchPayload);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$form = $formCrawler->form();
$form->setValues([
'mauticform[country]' => '',
'mauticform[state]' => '',
]);
$this->client->submit($form);
// Ensure the submission was created properly.
$submissions = $this->em->getRepository(Submission::class)->findAll();
Assert::assertCount(1, $submissions);
/** @var Submission $submission */
$submission = $submissions[0];
Assert::assertSame([
'country' => '',
], $submission->getResults());
// A contact should be created by the submission.
$contact = $submission->getLead();
Assert::assertSame(null, $contact->getCountry());
Assert::assertSame(null, $contact->getState());
// The previous request changes user to anonymous. We have to configure API again.
$this->setUpSymfony($this->configParams);
// Cleanup:
$this->client->request(Request::METHOD_DELETE, "/api/forms/{$formId}/delete");
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
}
public function testRequiredConditionalFieldIfRequiredStateShouldKickIn(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'fields' => [
[
'label' => 'Country',
'type' => 'country',
'alias' => 'country',
'leadField' => 'country',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Add conditional state field dependent on the country field:
$patchPayload = [
'fields' => [
[
'label' => 'State',
'type' => 'select',
'alias' => 'state',
'leadField' => 'state',
'parent' => $response['form']['fields'][0]['id'],
'isRequired' => true,
'conditions' => [
'expr' => 'in',
'any' => 0,
'values' => ['Australia'],
],
'properties' => [
'syncList' => 1,
'multiple' => 0,
],
],
],
];
$this->client->request(Request::METHOD_PATCH, "/api/forms/{$formId}/edit", $patchPayload);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$form = $formCrawler->form();
$form->setValues([
'mauticform[country]' => 'Australia',
'mauticform[state]' => '',
]);
$this->client->submit($form);
// Ensure the submission was created properly.
$submissions = $this->em->getRepository(Submission::class)->findAll();
// It should not create a submission now as the required field is now visible and empty.
Assert::assertCount(0, $submissions);
// The previous request changes user to anonymous. We have to configure API again.
$this->setUpSymfony($this->configParams);
// Cleanup:
$this->client->request(Request::METHOD_DELETE, "/api/forms/{$formId}/delete");
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
}
public function testProgressiveFormsWithMaximumFieldsDisplayedAtTime(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'progressiveProfilingLimit' => 2,
'fields' => [
[
'label' => 'Email',
'type' => 'email',
'alias' => 'email',
'leadField' => 'email',
'is_auto_fill' => 1,
'show_when_value_exists' => 0,
],
[
'label' => 'Firstname',
'type' => 'text',
'alias' => 'firstname',
'leadField' => 'firstname',
'is_auto_fill' => 1,
'show_when_value_exists' => 0,
],
[
'label' => 'Lastname',
'type' => 'text',
'alias' => 'lastname',
'leadField' => 'lastname',
'is_auto_fill' => 1,
'show_when_value_exists' => 0,
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
// show just one text field
$this->assertSame(1, $formCrawler->filter('.mauticform-text')->count());
}
public function testAddContactToCampaignByForm(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'campaign',
'isPublished' => true,
'fields' => [
[
'label' => 'Email',
'type' => 'email',
'alias' => 'email',
'leadField' => 'email',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
$campaignSources = ['forms' => [$formId => $formId]];
/** @var CampaignModel $campaignModel */
$campaignModel = static::getContainer()->get('mautic.campaign.model.campaign');
$publishedCampaign = new Campaign();
$publishedCampaign->setName('Published');
$publishedCampaign->setIsPublished(true);
$campaignModel->setLeadSources($publishedCampaign, $campaignSources, []);
$unpublishedCampaign = new Campaign();
$unpublishedCampaign->setName('Unpublished');
$unpublishedCampaign->setIsPublished(false);
$campaignModel->setLeadSources($unpublishedCampaign, $campaignSources, []);
$this->em->persist($publishedCampaign);
$this->em->persist($unpublishedCampaign);
$this->em->flush();
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$form = $formCrawler->form();
$form->setValues([
'mauticform[email]' => '[email protected]',
]);
$this->client->submit($form);
$submissions = $this->em->getRepository(Lead::class)->findAll();
Assert::assertCount(1, $submissions);
}
protected function beforeTearDown(): void
{
$tablePrefix = static::getContainer()->getParameter('mautic.db_table_prefix');
if ($this->connection->createSchemaManager()->tablesExist("{$tablePrefix}form_results_1_submission")) {
$this->connection->executeQuery("DROP TABLE {$tablePrefix}form_results_1_submission");
}
}
public function testFetchFormSubmissionsApiIfPermissionNotGrantedForUser(): void
{
// Create the test form via API.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'fields' => [
[
'label' => 'Country',
'type' => 'country',
'alias' => 'country',
'leadField' => 'country',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$form = $formCrawler->form();
$form->setValues([
'mauticform[country]' => 'Australia',
]);
$this->client->submit($form);
// Ensure the submission was created properly.
$submissions = $this->em->getRepository(Submission::class)->findAll();
Assert::assertCount(1, $submissions);
// Enable reboots so all the services and in-memory data are refreshed.
$this->client->enableReboot();
// fetch form submissions as Admin User
$this->client->request(Request::METHOD_GET, "/api/forms/{$formId}/submissions");
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$submission = $response['submissions'][0];
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
Assert::assertSame($formId, $submission['form']['id']);
Assert::assertGreaterThanOrEqual(1, $response['total']);
// Create non admin user
$user = $this->createUser();
// Fetch form submissions as non-admin-user who don't have the permission to view submissions
$this->client->request(Request::METHOD_GET, "/api/forms/{$formId}/submissions", [], [], [
'PHP_AUTH_USER' => $user->getUserIdentifier(),
'PHP_AUTH_PW' => $this->getUserPlainPassword(),
]);
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_FORBIDDEN, $clientResponse->getStatusCode(), $clientResponse->getContent());
}
private function createUser(): User
{
$role = new Role();
$role->setName('api_restricted');
$role->setDescription('Api Permission Not Granted');
$role->setIsAdmin(false);
$role->setRawPermissions(['form:forms' => ['viewown']]);
/** @var RoleRepository $roleRepository */
$roleRepository = $this->em->getRepository(Role::class);
$roleRepository->saveEntity($role);
$user = new User();
$user->setEmail('[email protected]');
$user->setUsername('non-admin-user');
$user->setFirstName('test');
$user->setLastName('test');
$user->setRole($role);
/** @var PasswordEncoderInterface $encoder */
$encoder = static::getContainer()->get('security.encoder_factory')->getEncoder($user);
$user->setPassword($encoder->encodePassword($this->getUserPlainPassword(), $user->getSalt()));
/** @var UserRepository $userRepo */
$userRepo = $this->em->getRepository(User::class);
$userRepo->saveEntities([$user]);
return $user;
}
public function testSendSubmissionWhenFieldHaveMysqlReservedWords(): void
{
// Create the test form.
$payload = [
'name' => 'Submission test form',
'description' => 'Form created via submission test',
'formType' => 'standalone',
'isPublished' => true,
'fields' => [
[
'label' => 'All',
'type' => 'text',
'alias' => 'all',
'leadField' => 'firstname',
],
[
'label' => 'Submit',
'type' => 'button',
],
],
'postAction' => 'return',
];
$this->client->request(Request::METHOD_POST, '/api/forms/new', $payload);
$clientResponse = $this->client->getResponse();
$response = json_decode($clientResponse->getContent(), true);
$formId = $response['form']['id'];
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent());
// Submit the form:
$crawler = $this->client->request(Request::METHOD_GET, "/form/{$formId}");
$formCrawler = $crawler->filter('form[id=mauticform_submissiontestform]');
$this->assertSame(1, $formCrawler->count());
$form = $formCrawler->form();
$form->setValues([
'mauticform[f_all]' => 'test',
]);
$this->client->submit($form);
// Ensure the submission was created properly.
$submissions = $this->em->getRepository(Submission::class)->findAll();
Assert::assertCount(1, $submissions);
/** @var Submission $submission */
$submission = $submissions[0];
Assert::assertSame([
'f_all' => 'test',
], $submission->getResults());
// A contact should be created by the submission.
$contact = $submission->getLead();
Assert::assertSame('test', $contact->getFirstname());
// The previous request changes user to anonymous. We have to configure API again.
$this->setUpSymfony($this->configParams);
$this->client->request(Request::METHOD_GET, "/s/forms/results/{$formId}");
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertStringContainsString('Results for Submission test form', $clientResponse->getContent());
// Cleanup:
$this->client->request(Request::METHOD_DELETE, "/api/forms/{$formId}/delete");
$clientResponse = $this->client->getResponse();
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent());
}
private function getUserPlainPassword(): string
{
return 'test-pass';
}
}