Initial commit
This commit is contained in:
63
tests/Feature/Forms/AnswerFormTest.php
Normal file
63
tests/Feature/Forms/AnswerFormTest.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
use Tests\Helpers\FormSubmissionDataFactory;
|
||||
|
||||
it('can answer a form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
// TODO: generate random response given a form and un-skip
|
||||
})->skip('Need to finish writing a class to generated random responses');
|
||||
|
||||
|
||||
it('can submit form if close date is in future', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'closes_at' => \Carbon\Carbon::now()->addDays(1)->toDateTimeString(),
|
||||
]);
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('can not submit closed form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'closes_at' => \Carbon\Carbon::now()->subDays(1)->toDateTimeString(),
|
||||
]);
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertStatus(403);
|
||||
});
|
||||
|
||||
it('can submit form till max submissions count is not reached at limit', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'max_submissions_count' => 3,
|
||||
]);
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||
|
||||
// Can submit form
|
||||
for($i=1;$i<=3;$i++){
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Now, can not submit form, Because it's reached at submission limit
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertStatus(403);
|
||||
});
|
||||
48
tests/Feature/Forms/CleanDatabaseTest.php
Normal file
48
tests/Feature/Forms/CleanDatabaseTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Spatie\Mailcoach\Domain\TransactionalMail\Models\TransactionalMail;
|
||||
|
||||
it('check form statistic for views & submissions counts', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, []);
|
||||
|
||||
// Create 10 views & submissions (in the past of 1 day so that it's cleaned)
|
||||
for($i=1;$i<=10;$i++){
|
||||
$submission = $form->submissions()->create();
|
||||
$submission->created_at = now()->subDay();
|
||||
$submission->save();
|
||||
$view = $form->views()->create();
|
||||
$view->created_at = now()->subDay();
|
||||
$view->save();
|
||||
}
|
||||
|
||||
// Create a submission & a view for another date
|
||||
$submission = $form->submissions()->create();
|
||||
$submission->created_at = now()->subDays(2);
|
||||
$submission->save();
|
||||
$view = $form->views()->create();
|
||||
$view->created_at = now()->subDays(2);
|
||||
$view->save();
|
||||
|
||||
// Run Command
|
||||
Artisan::call('forms:database-cleanup');
|
||||
|
||||
// Create 5 views & submissions
|
||||
for($i=1;$i<=5;$i++){
|
||||
$form->views()->create();
|
||||
$form->submissions()->create();
|
||||
}
|
||||
|
||||
// Now check counters
|
||||
$statistics = $form->statistics()->get();
|
||||
expect($form->views_count)->toBe(16);
|
||||
expect($form->submissions_count)->toBe(16);
|
||||
expect($form->views()->count())->toBe(5);
|
||||
expect($form->submissions()->count())->toBe(16);
|
||||
expect(count($statistics))->toBe(2); // 1 per day for 2 different dates
|
||||
expect($statistics[0]["date"])->toBe(now()->subDays(2)->toDateString());
|
||||
expect($statistics[0]["data"])->toBe(["views"=>1,"submissions"=>1]);
|
||||
expect($statistics[1]["date"])->toBe(now()->subDay()->toDateString());
|
||||
expect($statistics[1]["data"])->toBe(["views"=>10,"submissions"=>10]);
|
||||
});
|
||||
109
tests/Feature/Forms/ConfirmationEmailTest.php
Normal file
109
tests/Feature/Forms/ConfirmationEmailTest.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Mail\Forms\SubmissionConfirmationMail;
|
||||
|
||||
it('creates confirmation emails with the submitted data', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'send_submission_confirmation' => true,
|
||||
'notifications_include_submission' => true,
|
||||
'notification_sender' => 'Custom Sender',
|
||||
'notification_subject' => 'Test subject',
|
||||
'notification_body' => 'Test body',
|
||||
]);
|
||||
|
||||
$formData = [
|
||||
collect($form->properties)->first(function ($property) {
|
||||
return $property['type'] == 'email';
|
||||
})["id"] => "test@test.com",
|
||||
];
|
||||
$event = new \App\Events\Forms\FormSubmitted($form, $formData);
|
||||
$mailable = new SubmissionConfirmationMail($event);
|
||||
$mailable->assertSeeInHtml('Test body')
|
||||
->assertSeeInHtml('As a reminder, here are your answers:')
|
||||
->assertSeeInHtml('You are receiving this email because you answered the form:');
|
||||
});
|
||||
|
||||
it('creates confirmation emails without the submitted data', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'send_submission_confirmation' => true,
|
||||
'notifications_include_submission' => false,
|
||||
'notification_sender' => 'Custom Sender',
|
||||
'notification_subject' => 'Test subject',
|
||||
'notification_body' => 'Test body',
|
||||
]);
|
||||
|
||||
$formData = [
|
||||
collect($form->properties)->first(function ($property) {
|
||||
return $property['type'] == 'email';
|
||||
})["id"] => "test@test.com",
|
||||
];
|
||||
$event = new \App\Events\Forms\FormSubmitted($form, $formData);
|
||||
$mailable = new SubmissionConfirmationMail($event);
|
||||
$mailable->assertSeeInHtml('Test body')
|
||||
->assertDontSeeInHtml('As a reminder, here are your answers:')
|
||||
->assertSeeInHtml('You are receiving this email because you answered the form:');
|
||||
});
|
||||
|
||||
it('sends a confirmation email if needed', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'send_submission_confirmation' => true,
|
||||
'notifications_include_submission' => true,
|
||||
'notification_subject' => 'Test subject',
|
||||
]);
|
||||
$emailProperty = collect($form->properties)->first(function ($property) {
|
||||
return $property['type'] == 'email';
|
||||
});
|
||||
$formData = [
|
||||
$emailProperty["id"] => "test@test.com",
|
||||
];
|
||||
|
||||
Mail::fake();
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
|
||||
Mail::assertQueued(SubmissionConfirmationMail::class,
|
||||
function (SubmissionConfirmationMail $mail) use ($formData, $emailProperty) {
|
||||
return $mail->hasTo("test@test.com");
|
||||
});
|
||||
});
|
||||
|
||||
it('does not send a confirmation email if not needed', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'send_submission_confirmation' => false,
|
||||
]);
|
||||
$emailProperty = collect($form->properties)->first(function ($property) {
|
||||
return $property['type'] == 'email';
|
||||
});
|
||||
$formData = [
|
||||
$emailProperty["id"] => "test@test.com",
|
||||
];
|
||||
|
||||
Mail::fake();
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
|
||||
Mail::assertNotQueued(SubmissionConfirmationMail::class,
|
||||
function (SubmissionConfirmationMail $mail) use ($formData, $emailProperty) {
|
||||
return $mail->hasTo("test@test.com");
|
||||
});
|
||||
});
|
||||
|
||||
26
tests/Feature/Forms/CreateDynamicSelectOptionTest.php
Normal file
26
tests/Feature/Forms/CreateDynamicSelectOptionTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
use Tests\Helpers\FormSubmissionDataFactory;
|
||||
|
||||
it('can submit form with dyanamic select option', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$selectionsPreData = [];
|
||||
$form->properties = collect($form->properties)->map(function ($property) use (&$selectionsPreData) {
|
||||
if(in_array($property['type'], ['select','multi_select'])){
|
||||
$property["allow_creation"] = true;
|
||||
$selectionsPreData[$property['id']] = ($property['type'] == "select") ? "New single select - ".time() : ["New multi select - ".time()];
|
||||
}
|
||||
return $property;
|
||||
})->toArray();
|
||||
$form->update();
|
||||
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form, $selectionsPreData);
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
20
tests/Feature/Forms/FormCaptchaTest.php
Normal file
20
tests/Feature/Forms/FormCaptchaTest.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
it('create form with captcha and raise validation issue', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'use_captcha' => true,
|
||||
]);
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), [])
|
||||
->assertStatus(422)
|
||||
->assertJson([
|
||||
'message' => 'Please complete the captcha.',
|
||||
'errors' => [
|
||||
'h-captcha-response' => [
|
||||
'Please complete the captcha.',
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
58
tests/Feature/Forms/FormLogicTest.php
Normal file
58
tests/Feature/Forms/FormLogicTest.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
|
||||
|
||||
it('create form with logic', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "title",
|
||||
'name' => "Name",
|
||||
'type' => 'title',
|
||||
'hidden' => false,
|
||||
'required' => true,
|
||||
'logic' => [
|
||||
"conditions" => [
|
||||
"operatorIdentifier"=> "and",
|
||||
"children"=> [
|
||||
[
|
||||
"identifier"=> "email",
|
||||
"value"=> [
|
||||
"operator"=> "is_empty",
|
||||
"property_meta"=> [
|
||||
'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124",
|
||||
"type"=> "email",
|
||||
],
|
||||
"value"=> true
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"actions" => ['make-it-optional']
|
||||
]
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
$this->getJson(route('forms.show', $form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) use ($form) {
|
||||
return $json->where('id', $form->id)
|
||||
->where('properties', function($values){
|
||||
return (count($values[0]['logic']) > 0);
|
||||
})
|
||||
->etc();
|
||||
});
|
||||
|
||||
// Should submit form
|
||||
$forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ""];
|
||||
$this->postJson(route('forms.answer', $form->slug), $forData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
97
tests/Feature/Forms/FormPasswordTest.php
Normal file
97
tests/Feature/Forms/FormPasswordTest.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\Helpers\FormSubmissionDataFactory;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
$this->password = "12345";
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$this->form = $this->createForm($user, $workspace, [
|
||||
'password' => $this->password,
|
||||
]);
|
||||
$this->formData = FormSubmissionDataFactory::generateSubmissionData($this->form);
|
||||
});
|
||||
|
||||
|
||||
it('can allow form owner to access and submit form without password', function () {
|
||||
// As Form Owner so can access form without password
|
||||
$this->getJson(route('forms.show', $this->form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) {
|
||||
return $json->where('id', $this->form->id)
|
||||
->where('has_password', true)
|
||||
->where('is_password_protected', false)
|
||||
->etc();
|
||||
});
|
||||
|
||||
// As Form Owner so can submit form without password
|
||||
$this->postJson(route('forms.answer', $this->form->slug), $this->formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('can not access form without password for guest user', function () {
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->getJson(route('forms.show', $this->form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) {
|
||||
return $json->where('id', $this->form->id)
|
||||
->where('has_password', true)
|
||||
->where('is_password_protected', true)
|
||||
->etc();
|
||||
});
|
||||
});
|
||||
|
||||
it('can not submit form without password for guest user', function () {
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->postJson(route('forms.answer', $this->form->slug), $this->formData)
|
||||
->assertStatus(403)
|
||||
->assertJson([
|
||||
'status' => 'Unauthorized',
|
||||
'message' => 'Form is password protected.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('can not submit form with wrong password for guest user', function () {
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->withHeaders(['form-password'=>hash('sha256', 'WRONGPASSWORD')])
|
||||
->postJson(route('forms.answer', $this->form->slug), $this->formData)
|
||||
->assertStatus(403)
|
||||
->assertJson([
|
||||
'status' => 'Unauthorized',
|
||||
'message' => 'Form is password protected.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('can access form with right password for guest user', function () {
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->withHeaders(['form-password'=>hash('sha256', $this->password)])
|
||||
->getJson(route('forms.show', $this->form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) {
|
||||
return $json->where('id', $this->form->id)
|
||||
->where('has_password', true)
|
||||
->where('is_password_protected', false)
|
||||
->etc();
|
||||
});
|
||||
});
|
||||
|
||||
it('can submit form with right password for guest user', function () {
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->withHeaders(['form-password'=>hash('sha256', $this->password)])
|
||||
->postJson(route('forms.answer', $this->form->slug), $this->formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
138
tests/Feature/Forms/FormPropertyLogicTest.php
Normal file
138
tests/Feature/Forms/FormPropertyLogicTest.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
use App\Rules\FormPropertyLogicRule;
|
||||
|
||||
it('can validate form logic rules for actions', function () {
|
||||
$rules = [
|
||||
'properties.*.logic' => ['array', 'nullable', new FormPropertyLogicRule()]
|
||||
];
|
||||
|
||||
$data = [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "title",
|
||||
'name' => "Name",
|
||||
'type' => 'title',
|
||||
'hidden' => false,
|
||||
'required' => false,
|
||||
'logic' => [
|
||||
"conditions" => null,
|
||||
"actions" => []
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
$validatorObj = $this->app['validator']->make($data, $rules);
|
||||
$this->assertTrue($validatorObj->passes());
|
||||
|
||||
|
||||
$data = [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "title",
|
||||
'name' => "Name",
|
||||
'type' => 'title',
|
||||
'hidden' => true,
|
||||
'required' => false,
|
||||
'logic' => [
|
||||
"conditions" => null,
|
||||
"actions" => ['hide-block']
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
$validatorObj = $this->app['validator']->make($data, $rules);
|
||||
$this->assertFalse($validatorObj->passes());
|
||||
expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic actions for Name are not valid.");
|
||||
|
||||
$data = [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "text",
|
||||
'name' => "Custom Test",
|
||||
'type' => 'nf-text',
|
||||
'logic' => [
|
||||
"conditions" => null,
|
||||
"actions" => ['require-answer']
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
$validatorObj = $this->app['validator']->make($data, $rules);
|
||||
$this->assertFalse($validatorObj->passes());
|
||||
expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic actions for Custom Test are not valid.");
|
||||
});
|
||||
|
||||
|
||||
it('can validate form logic rules for conditions', function () {
|
||||
$rules = [
|
||||
'properties.*.logic' => ['array', 'nullable', new FormPropertyLogicRule()]
|
||||
];
|
||||
|
||||
$data = [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "title",
|
||||
'name' => "Name",
|
||||
'type' => 'text',
|
||||
'hidden' => false,
|
||||
'required' => false,
|
||||
'logic' => [
|
||||
"conditions" => [
|
||||
"operatorIdentifier"=> "and",
|
||||
"children"=> [
|
||||
[
|
||||
"identifier"=> "title",
|
||||
"value"=> [
|
||||
"operator"=> "equals",
|
||||
"property_meta"=> [
|
||||
"id"=> "title",
|
||||
"type"=> "text"
|
||||
],
|
||||
"value"=> "TEST"
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"actions" => []
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$validatorObj = $this->app['validator']->make($data, $rules);
|
||||
$this->assertTrue($validatorObj->passes());
|
||||
|
||||
$data = [
|
||||
'properties' => [
|
||||
[
|
||||
'id' => "title",
|
||||
'name' => "Name",
|
||||
'type' => 'text',
|
||||
'hidden' => false,
|
||||
'required' => false,
|
||||
'logic' => [
|
||||
"conditions" => [
|
||||
"operatorIdentifier"=> "and",
|
||||
"children"=> [
|
||||
[
|
||||
"identifier"=> "title",
|
||||
"value"=> [
|
||||
"operator"=> "starts_with",
|
||||
"property_meta"=> [
|
||||
"id"=> "title",
|
||||
"type"=> "text"
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"actions" => []
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$validatorObj = $this->app['validator']->make($data, $rules);
|
||||
$this->assertFalse($validatorObj->passes());
|
||||
expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic conditions for Name are not complete.");
|
||||
});
|
||||
65
tests/Feature/Forms/FormStatTest.php
Normal file
65
tests/Feature/Forms/FormStatTest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
it('check formstat chart data', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, []);
|
||||
|
||||
$views = [];
|
||||
$submissions = [];
|
||||
// Create 10 views & submissions for past days
|
||||
for($i=1;$i<=10;$i++){
|
||||
$date = now()->subDays($i);
|
||||
$dateString = $date->format('d-m-Y');
|
||||
|
||||
$submission = $form->submissions()->create();
|
||||
$submission->created_at = $date;
|
||||
$submission->save();
|
||||
$view = $form->views()->create();
|
||||
$view->created_at = $date;
|
||||
$view->save();
|
||||
|
||||
$views[$dateString] = isset($views[$dateString]) ? ($views[$dateString] + 1) : 1;
|
||||
$submissions[$dateString] = isset($submissions[$dateString]) ? ($submissions[$dateString] + 1) : 1;
|
||||
}
|
||||
|
||||
// Run Command
|
||||
Artisan::call('forms:database-cleanup');
|
||||
|
||||
// Create 5 views & submissions
|
||||
for($i=1;$i<=5;$i++){
|
||||
$form->views()->create();
|
||||
$form->submissions()->create();
|
||||
|
||||
$dateString = now()->format('d-m-Y');
|
||||
$views[$dateString] = isset($views[$dateString]) ? ($views[$dateString] + 1) : 1;
|
||||
$submissions[$dateString] = isset($submissions[$dateString]) ? ($submissions[$dateString] + 1) : 1;
|
||||
}
|
||||
|
||||
// Now check chart data
|
||||
$this->getJson(route('open.workspaces.form.stats', [$workspace->id, $form->id]))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (\Illuminate\Testing\Fluent\AssertableJson $json) use ($views, $submissions) {
|
||||
return $json->whereType('views', 'array')
|
||||
->whereType('submissions', 'array')
|
||||
->where('views', function($values) use ($views) {
|
||||
foreach($values as $date=>$count){
|
||||
if((isset($views[$date]) && $views[$date] != $count) || (!isset($views[$date]) && $count != 0)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
->where('submissions', function($values) use ($submissions) {
|
||||
foreach($values as $date=>$count){
|
||||
if((isset($submissions[$date]) && $submissions[$date] != $count) || (!isset($submissions[$date]) && $count != 0)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
->etc();
|
||||
});
|
||||
|
||||
});
|
||||
155
tests/Feature/Forms/FormTest.php
Normal file
155
tests/Feature/Forms/FormTest.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
|
||||
it('can create a contact form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->makeForm($user, $workspace);
|
||||
$formData = new \App\Http\Resources\FormResource($form);
|
||||
|
||||
$response = $this->postJson(route('open.forms.store', $formData->toArray(request())))
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form created.'
|
||||
]);
|
||||
|
||||
expect($workspace->forms()->count())->toBe(1);
|
||||
$this->assertDatabaseHas('forms', [
|
||||
'id' => $response->json('form.id'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('can fetch forms', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$this->getJson(route('open.workspaces.forms.index', $workspace->id))
|
||||
->assertSuccessful()
|
||||
->assertJsonCount(1)
|
||||
->assertJson(function (AssertableJson $json) use ($form) {
|
||||
return $json->where('0.id', $form->id)
|
||||
->whereType('0.title', 'string')
|
||||
->whereType('0.properties', 'array');
|
||||
});
|
||||
});
|
||||
|
||||
it('can update a form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
$newFormData = $this->makeForm($user, $workspace);
|
||||
$form->fill((new \App\Http\Resources\FormResource($newFormData))->toArray(request()));
|
||||
|
||||
$formData = (new \App\Http\Resources\FormResource($form))->toArray(request());
|
||||
|
||||
$this->putJson(route('open.forms.update', $form->id), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form updated.'
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('forms', [
|
||||
'id' => $form->id,
|
||||
'title' => $form->title,
|
||||
'description' => $form->description,
|
||||
]);
|
||||
});
|
||||
|
||||
it('can regenerate a form url', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
$newFormData = $this->makeForm($user, $workspace);
|
||||
$form->update([
|
||||
'title' => $newFormData->title,
|
||||
]);
|
||||
$form->generateSlug();
|
||||
$newSlug = $form->slug;
|
||||
|
||||
$this->putJson(route('open.forms.regenerate-link', [$form->id, 'uuid']))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) {
|
||||
return $json->where('type', 'success')
|
||||
->where('form.slug', function ($value) {
|
||||
if (!is_string($value) || (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/',
|
||||
$value) !== 1)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
->etc();
|
||||
});
|
||||
|
||||
$this->putJson(route('open.forms.regenerate-link', [$form->id, 'slug']))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) use ($newSlug) {
|
||||
return $json->where('type', 'success')
|
||||
->where('form.slug', $newSlug)
|
||||
->etc();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('can duplicate a form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$response = $this->postJson(route('open.forms.duplicate', $form->id))
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form successfully duplicated.'
|
||||
]);
|
||||
|
||||
expect($user->forms()->count())->toBe(2);
|
||||
expect($workspace->forms()->count())->toBe(2);
|
||||
$this->assertDatabaseHas('forms', [
|
||||
'id' => $response->json('new_form.id'),
|
||||
'title' => 'Copy of '.$form->title,
|
||||
'description' => $form->description,
|
||||
]);
|
||||
});
|
||||
|
||||
it('can delete a form', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$this->deleteJson(route('open.forms.destroy', $form->id))
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form was deleted.'
|
||||
]);
|
||||
expect($user->forms()->count())->toBe(0);
|
||||
expect($workspace->forms()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('can create form with dark mode', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace, [
|
||||
'dark_mode' => "dark",
|
||||
]);
|
||||
$formData = (new \App\Http\Resources\FormResource($form))->toArray(request());
|
||||
|
||||
$this->postJson(route('open.forms.store', $formData))
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form created.'
|
||||
]);
|
||||
|
||||
$this->getJson(route('forms.show', $form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (AssertableJson $json) use ($form) {
|
||||
return $json->where('id', $form->id)
|
||||
->where('dark_mode', 'dark')
|
||||
->etc();
|
||||
});
|
||||
});
|
||||
38
tests/Feature/Forms/FormViewsTest.php
Normal file
38
tests/Feature/Forms/FormViewsTest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
it('can see form without counting view for form owner', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$this->getJson(route('forms.show', $form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (\Illuminate\Testing\Fluent\AssertableJson $json) use ($form) {
|
||||
return $json->where('id', $form->id)
|
||||
->where('title', $form->title)
|
||||
->whereType('properties', 'array')
|
||||
->etc();
|
||||
});
|
||||
|
||||
expect($form->views()->count())->toBe(0);
|
||||
});
|
||||
|
||||
|
||||
it('can see form and count view for guest', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
|
||||
$this->actingAsGuest();
|
||||
|
||||
$this->getJson(route('forms.show', $form->slug))
|
||||
->assertSuccessful()
|
||||
->assertJson(function (\Illuminate\Testing\Fluent\AssertableJson $json) use ($form) {
|
||||
return $json->where('id', $form->id)
|
||||
->where('title', $form->title)
|
||||
->whereType('properties', 'array')
|
||||
->etc();
|
||||
});
|
||||
|
||||
expect($form->views()->count())->toBe(1);
|
||||
});
|
||||
35
tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php
Normal file
35
tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
use Tests\Helpers\FormSubmissionDataFactory;
|
||||
use App\Models\User;
|
||||
|
||||
it('can validate Update Workspace Select Option Job', function () {
|
||||
$user = $this->actingAsUser();
|
||||
$workspace = $this->createUserWorkspace($user);
|
||||
$form = $this->createForm($user, $workspace);
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
|
||||
$formData = FormSubmissionDataFactory::generateSubmissionData($form);
|
||||
$this->postJson(route('forms.answer', $form->slug), $formData)
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Form submission saved.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('can validate scope with active subscription', function () {
|
||||
$this->createProUser();
|
||||
$this->createUser();
|
||||
$this->createProUser();
|
||||
$this->createProUser();
|
||||
$this->createUser();
|
||||
|
||||
expect(User::WithActiveSubscription()->count())->toBe(3);
|
||||
});
|
||||
38
tests/Feature/LoginTest.php
Normal file
38
tests/Feature/LoginTest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
it('can login to Forms', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->postJson('/api/login', [
|
||||
'email' => $user->email,
|
||||
'password' => 'password',
|
||||
])
|
||||
->assertSuccessful()
|
||||
->assertJsonStructure(['token', 'expires_in'])
|
||||
->assertJson(['token_type' => 'bearer']);
|
||||
});
|
||||
|
||||
it('can fetch current user', function () {
|
||||
$this->actingAs(User::factory()->create())
|
||||
->getJson('/api/user')
|
||||
->assertSuccessful()
|
||||
->assertJsonStructure(['id', 'name', 'email']);
|
||||
});
|
||||
|
||||
it('can log out', function () {
|
||||
$this->postJson('/api/login', [
|
||||
'email' => User::factory()->create()->email,
|
||||
'password' => 'password',
|
||||
])->assertSuccessful();
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$this->postJson("/api/logout")
|
||||
->assertSuccessful();
|
||||
|
||||
$this->assertGuest();
|
||||
$this->getJson("/api/user")
|
||||
->assertStatus(401);
|
||||
});
|
||||
|
||||
33
tests/Feature/RegisterTest.php
Normal file
33
tests/Feature/RegisterTest.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
it('can register', function () {
|
||||
$this->postJson('/api/register', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@test.app',
|
||||
'hear_about_us' => 'google',
|
||||
'password' => 'secret',
|
||||
'password_confirmation' => 'secret',
|
||||
])
|
||||
->assertSuccessful()
|
||||
->assertJsonStructure(['id', 'name', 'email']);
|
||||
$this->assertDatabaseHas('users', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@test.app'
|
||||
]);
|
||||
});
|
||||
|
||||
it('cannot register with existing email', function () {
|
||||
User::factory()->create(['email' => 'test@test.app']);
|
||||
|
||||
$this->postJson('/api/register', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@test.app',
|
||||
'password' => 'secret',
|
||||
'password_confirmation' => 'secret',
|
||||
])
|
||||
->assertStatus(422)
|
||||
->assertJsonValidationErrors(['email']);
|
||||
});
|
||||
32
tests/Feature/SettingsTest.php
Normal file
32
tests/Feature/SettingsTest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Tests\TestCase;
|
||||
|
||||
it('update profile info',function() {
|
||||
$this->actingAs($user = User::factory()->create())
|
||||
->patchJson('/api/settings/profile', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@test.app',
|
||||
])
|
||||
->assertSuccessful()
|
||||
->assertJsonStructure(['id', 'name', 'email']);
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $user->id,
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@test.app',
|
||||
]);
|
||||
});
|
||||
|
||||
it('update password',function() {
|
||||
$this->actingAs($user = User::factory()->create())
|
||||
->patchJson('/api/settings/password', [
|
||||
'password' => 'updated',
|
||||
'password_confirmation' => 'updated',
|
||||
])
|
||||
->assertSuccessful();
|
||||
|
||||
$this->assertTrue(Hash::check('updated', $user->password));
|
||||
});
|
||||
24
tests/Feature/VerificationTest.php
Normal file
24
tests/Feature/VerificationTest.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Notifications\VerifyEmail;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Tests\TestCase;
|
||||
|
||||
it('can verify email', function () {
|
||||
$user = User::factory()->create(['email_verified_at' => null]);
|
||||
$url = URL::temporarySignedRoute('verification.verify', now()->addMinutes(60), ['user' => $user->id]);
|
||||
|
||||
Event::fake();
|
||||
|
||||
$this->postJson($url)
|
||||
->assertSuccessful()
|
||||
->assertJsonFragment(['status' => 'Your email has been verified!']);
|
||||
|
||||
Event::assertDispatched(Verified::class, function (Verified $e) use ($user) {
|
||||
return $e->user->is($user);
|
||||
});
|
||||
});
|
||||
36
tests/Feature/WorkspaceTest.php
Normal file
36
tests/Feature/WorkspaceTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
it('can create and delete Workspace', function () {
|
||||
$user = $this->actingAsUser();
|
||||
|
||||
for($i=1;$i<=3;$i++){
|
||||
$this->postJson(route('open.workspaces.create'), [
|
||||
'name' => 'Workspace Test - '.$i,
|
||||
'icon' => '🧪',
|
||||
])
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Workspace created.'
|
||||
]);
|
||||
}
|
||||
|
||||
expect($user->workspaces()->count())->toBe(3);
|
||||
|
||||
$i=0;
|
||||
foreach($user->workspaces as $workspace){
|
||||
$i++;
|
||||
if($i !== 3){
|
||||
$this->deleteJson(route('open.workspaces.delete', $workspace->id))
|
||||
->assertSuccessful()
|
||||
->assertJson([
|
||||
'type' => 'success',
|
||||
'message' => 'Workspace deleted.'
|
||||
]);
|
||||
}else{
|
||||
// Last workspace can not delete
|
||||
$this->deleteJson(route('open.workspaces.delete', $workspace->id))
|
||||
->assertStatus(403);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user