Spaces:
No application file
No application file
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'; | |
} | |
} | |