ldc-crm/tests/CRM/ApiV2/QuestionTest.php
2025-08-05 15:30:34 +02:00

307 lines
11 KiB
PHP

<?php
namespace Tests\CRM\ApiV2;
use App\Enums\ApiError;
use App\Enums\ApiStatus;
use App\Models\Customer;
use App\Models\ModelAnswer;
use App\Models\Question;
use App\Models\Service;
use Illuminate\Support\Facades\DB;
class QuestionTest extends ApiBase
{
/**
* Test get all service questions.
* route: apiV2.questions.index
*
* @return void
*/
public function testQuestionIndex(): void
{
extract($this->getCustomer());
/** @var \Illuminate\Database\Eloquent\Collection $questions */
$questions = Question::whereHas('brand', function ($q) use ($service) {
$q->whereId($service->brand->id);
})->with('answers')->get()->keyBy('id');
$response = $this->callApiWithToken($service, 'get', route('apiV2.questions.index'));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$json->assertStructure([
'data' => [
'*' => [
'id',
'type',
'question',
'answers' => [
'*' => [
'id',
'answer'
]
],
]
]
]);
// Should contain questions with answers.
foreach ($json->json('data') as $question) {
$this->assertTrue($questions->contains($question['id']));
$DBquestion = $questions->get($question['id']);
$this->assertEquals($DBquestion->type->value(), $question['type']);
$this->assertEquals($DBquestion->question, $question['question']);
foreach ($question['answers'] as $answer) {
$answers = $DBquestion->answers->keyBy('id');
$this->assertTrue($answers->contains($answer['id']));
$DBanswer = $answers->get($answer['id']);
$this->assertEquals($DBanswer->answer, $answer['answer']);
}
}
}
/**
* Test get all service questions with customer answers.
* route: apiV2.questions.indexWithResponse
*
* @return void
*/
public function testQuestionIndexWithAnswers(): void
{
extract($this->getCustomer(true, false));
/** @var \Illuminate\Database\Eloquent\Collection $questions */
$questions = Question::whereHas('brand', function ($q) use ($service) {
$q->whereId($service->brand->id);
})->with('answers')->get()->keyBy('id');
// * Make sure a customer answer is set.
$firstAnswer = $questions->first()->answers->first();
$firstAnswer->load('question');
/** @var \App\Models\ModelAnswer $modelAnswer */
DB::table('model_answer')->insert([
'model_type' => Customer::class,
'model_id' => $customer->getKey(),
'answer_id' => $firstAnswer->getKey(),
]);
// * Call
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.indexWithResponse',
['serviceCustomer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$json->assertStructure([
'data' => [
'*' => [
'id',
'type',
'question',
'answers' => [
'*' => [
'id',
'answer'
]
],
'customerAnswers'
]
]
]);
// Should contain questions with answers.
foreach ($json->json('data') as $question) {
$this->assertTrue($questions->contains($question['id']));
$DBquestion = $questions->get($question['id']);
$this->assertEquals($DBquestion->type->value(), $question['type']);
$this->assertEquals($DBquestion->question, $question['question']);
foreach ($question['answers'] as $answer) {
$answers = $DBquestion->answers->keyBy('id');
$this->assertTrue($answers->contains($answer['id']));
$DBanswer = $answers->get($answer['id']);
$this->assertEquals($DBanswer->answer, $answer['answer']);
}
if ($firstAnswer->question->id === $DBquestion->id) {
$this->assertEquals($question['customerAnswers'][0]['id'], $firstAnswer->id);
$this->assertEquals($question['customerAnswers'][0]['answer'], $firstAnswer->answer);
}
}
}
/**
* Test get all service questions with customer answers when customer is unknown.
* route: apiV2.questions.indexWithResponse
*
* @return void
*/
public function testQuestionIndexWithAnswersWhenCustomerNotFound(): void
{
extract($this->getCustomer(true, false));
$service = Service::whereHas('brand', function ($q) use ($brand) {
$q->where('id', '!=', $brand->id);
})->firstOrFail();
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.indexWithResponse',
['serviceCustomer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::modelNotFound->value(), $json->json('data.code'));
}
/**
* Test get all service questions with customer answers when customer is unknown.
* route: apiV2.questions.unAnsweredBy
*
* @return void
*/
public function testCustomerUnAnsweredIndex(): void
{
extract($this->getCustomer(true, false));
/** @var \Illuminate\Database\Eloquent\Collection $questions */
$questions = Question::whereHas('brand', function ($q) use ($service) {
$q->whereId($service->brand->id);
})->with('answers')->get()->keyBy('id');
// * Make sure a customer answer is set.
$firstAnswer = $questions->first()->answers->first();
$firstAnswer->load('question');
/** @var \App\Models\ModelAnswer $modelAnswer */
DB::table('model_answer')->insert([
'model_type' => Customer::class,
'model_id' => $customer->getKey(),
'answer_id' => $firstAnswer->getKey(),
]);
// * Call
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.unAnsweredBy',
['serviceCustomer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$json->assertStructure([
'data' => [
'*' => [
'id',
'type',
'question',
'answers' => [
'*' => [
'id',
'answer'
]
]
]
]
]);
// Should contain questions with answers.
foreach ($json->json('data') as $question) {
$this->assertTrue($questions->contains($question['id']));
$DBquestion = $questions->get($question['id']);
$this->assertEquals($DBquestion->type->value(), $question['type']);
$this->assertEquals($DBquestion->question, $question['question']);
foreach ($question['answers'] as $answer) {
$answers = $DBquestion->answers->keyBy('id');
$this->assertTrue($answers->contains($answer['id']));
$DBanswer = $answers->get($answer['id']);
$this->assertEquals($DBanswer->answer, $answer['answer']);
}
$this->assertNotEquals(
$firstAnswer->question->id,
$DBquestion->id,
'This question has been answered by our user'
);
}
}
/**
* Test get all service questions unanswered by customer when customer is unknown.
* route: apiV2.questions.indexWithResponse
*
* @return void
*/
public function testUnAnsweredIndexWhenCustomerNotFound(): void
{
extract($this->getCustomer(true, false));
$service = Service::whereHas('brand', function ($q) use ($brand) {
$q->where('id', '!=', $brand->id);
})->firstOrFail();
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.unAnsweredBy',
['serviceCustomer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::modelNotFound->value(), $json->json('data.code'));
}
/**
* Test save customer answer.
* route: apiV2.customers.answers.store
*
* @return void
*/
public function testQuestionSetAnswer(): void
{
extract($this->getCustomer(true, false));
$question = Question::whereHas('brand', function ($q) use ($brand) {
$q->whereId($brand->id);
})->whereHas('answers', function ($q) use ($customer) {
$q->whereDoesntHave('customers', function ($q) use ($customer) {
$q->whereId($customer->id);
});
})->inRandomOrder()->firstOrFail();
$answer = $question->answers->first();
$response = $this->callApiWithToken($service, 'post', route(
'apiV2.customers.answers.store',
['serviceCustomer' => $info->hashcode]
), [
'question' => $question->id,
'answers' => [$answer->id]
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$this->assertTrue(
ModelAnswer::query()->where([
['model_type', Customer::class],
['model_id', $customer->getKey()],
['answer_id', $answer->getKey()]
])->exists(),
'Question should have been answered.'
);
}
/**
* Test get all save customer answers when customer is unknown.
* route: apiV2.questions.indexWithResponse
*
* @return void
*/
public function testQuestionSetAnswerWhenCustomerNotFound(): void
{
extract($this->getCustomer(true, false));
$service = Service::whereHas('brand', function ($q) use ($brand) {
$q->where('id', '!=', $brand->id);
})->firstOrFail();
$response = $this->callApiWithToken($service, 'post', route(
'apiV2.customers.answers.store',
['serviceCustomer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::modelNotFound->value(), $json->json('data.code'));
}
}