- tag 2.0.1

- Add Questions segementation
- Fix Customer delete Tests
This commit is contained in:
Jérémy Munsch 2021-08-11 17:25:24 +02:00
parent 642d3cce08
commit 787ee5a4c5
30 changed files with 533 additions and 46 deletions

View file

@ -7,6 +7,7 @@ use App\Enums\ApiStatus;
use App\Enums\ArcadiaMailType;
use App\Enums\ArcadiaOrderType;
use App\Enums\Country;
use App\Enums\QuestionType;
use App\Exceptions\Api\V2\ApiErrorException;
use App\Exceptions\Api\V2\CrmException;
use Illuminate\Console\Command;
@ -106,7 +107,8 @@ class GenerateCrmClient extends Command
ApiStatus::class,
ArcadiaMailType::class,
ArcadiaOrderType::class,
Country::class
Country::class,
QuestionType::class
], 'Enums');
}

View file

@ -3,8 +3,28 @@
namespace App\Http\Controllers\Api\V2;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\V2\StoreCustomerAnswers;
use App\Models\Answer;
use App\Models\Customer;
use App\Models\Service;
use Illuminate\Http\JsonResponse;
class AnswerController extends Controller
{
//
/**
* Store the customer answers
*
* @param \App\Http\Requests\Api\V2\StoreCustomerAnswers $request
* @param \App\Models\Service $service
* @param \App\Models\Customer $customer
* @return \Illuminate\Http\JsonResponse
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
public function storeCustomerAnswers(StoreCustomerAnswers $request, Service $service, Customer $customer): JsonResponse
{
$this->authorize('customerBelongsToService', $customer);
$answersID = Answer::whereIn('id', $request->answers)->pluck('id')->toArray();
$customer->answers()->sync($answersID);
return \response()->json();
}
}

View file

@ -32,11 +32,13 @@ class ArcadiaController extends Controller
{
public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request, Customer $customer, Service $service)
{
$this->authorize('customerBelongsToService', $customer);
return $this->handleArcadiaMail($request, ArcadiaMailType::default(), $customer, $service);
}
public function outgoingMailGame(SendArchadiaGameMailRequest $request, Customer $customer, Service $service)
{
$this->authorize('customerBelongsToService', $customer);
return $this->handleArcadiaMail($request, ArcadiaMailType::game(), $customer, $service);
}

View file

@ -73,6 +73,7 @@ class CustomerController extends Controller
*/
public function show(Customer $customer, Service $service): JsonResource
{
$this->authorize('customerBelongsToService', $customer);
return new CustomerResource($service->brand, $customer);
}
@ -86,6 +87,7 @@ class CustomerController extends Controller
*/
public function update(UpdateCustomerRequest $request, Customer $customer, Service $service): JsonResource
{
$this->authorize('customerBelongsToService', $customer);
// To correct with create
$customer->fill($request->all());
if ($customer->saveOrFail() === false) {
@ -117,6 +119,7 @@ class CustomerController extends Controller
*/
public function destroy(Customer $customer, Service $service): JsonResponse
{
$this->authorize('customerBelongsToService', $customer);
// TODO : A voir pour les stats, obuton dans le bo qui permet de faire les stats sur les customer puis supprimer
// TODO : Gestion avec mesBR
/** @var \App\Models\CustomerInfo */
@ -124,13 +127,31 @@ class CustomerController extends Controller
/** @var \App\Models\CustomerLogin */
$customerLogin = $customer->login($service->brand)->firstOrFail();
if (!$customerInfo->delete() || !$customerLogin->delete()) {
throw new CrmException(sprintf('Could not delete customer %d for brand %d', $customer, $service->brand));
}
if (
!$customerInfo->delete() ||
!$customerLogin->delete() ||
$customer->optInHistory()->whereHas('brand', function ($q) use ($service) {
$q->where('id', $service->brand_id);
})->delete() === false
) {
throw new CrmException(sprintf(
'Could not delete customer %d for brand %d',
$customer->id,
$service->brand->id
));
};
if (!$customer->logins()->count() and !$customer->infos()->count()) {
$logins = $customer->logins()->count();
$infos = $customer->infos()->count();
$history = $customer->optInHistory()->count();
// If customer is not associated with any brand then delete
if (!$logins and !$infos and !$history) {
if ($customer->delete() === false) {
throw new CrmException(sprintf('Could not delete customer %d', $customer));
throw new CrmException(sprintf(
'Could not delete customer %d',
$customer->id
));
}
}
@ -176,6 +197,7 @@ class CustomerController extends Controller
*/
public function activateAccount(Customer $customer, Service $service)
{
$this->authorize('customerBelongsToService', $customer);
$login = $customer->login($service->brand)->firstOrFail();
if ($login->status === 0) {

View file

@ -3,8 +3,69 @@
namespace App\Http\Controllers\Api\V2;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\V2\QuestionsResource;
use App\Models\Answer;
use App\Models\Customer;
use App\Models\Question;
use App\Models\Service;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
class QuestionController extends Controller
{
//
/**
* Display all specified resources.
*
* @param \App\Models\Service $service
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed
public function index(Service $service): ResourceCollection
{
return new QuestionsResource($service->brand->questions);
}
/**
* Display all specified resources.
*
* @param \App\Models\Service $service
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed
public function indexWithResponse(Service $service, Customer $customer): ResourceCollection
{
$this->authorize('customerBelongsToService', $customer);
$customerAnswers = Answer::whereHas('customers', function ($q) use ($customer) {
$q->whereId($customer->id);
})->get();
$customerAnswers = Answer::whereHas('customers', function ($q) use ($customer) {
$q->whereId($customer->id);
})->whereHas('question', function ($q) use ($service) {
$q->whereHas('brand', function ($q) use ($service) {
$q->whereId($service->brand->id);
});
})->get();
return new QuestionsResource($service->brand->questions, $customerAnswers);
}
/**
* Display all specified resource by customer.
*
* @param \App\Models\Service $service
* @param \App\Models\Customer $customer
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed
public function unAnsweredBy(Service $service, Customer $customer): JsonResource
{
$this->authorize('customerBelongsToService', $customer);
$questions = Question::whereHas('brand', function ($q) use ($service) {
$q->where('id', $service->brand->id);
})->whereDoesntHave('answers', function ($q) use ($customer) {
$q->whereIn('id', Answer::whereHas('customers', function ($q) use ($customer) {
$q->where('id', $customer->id);
})->pluck('id'));
})->with('answers')->get();
return new QuestionsResource($questions);
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Http\Requests\Api\V2;
use App\Models\Answer;
use App\Models\Question;
class StoreCustomerAnswers extends BaseApiRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
// resolve Service
$service = app()->make(\App\Models\Service::class);
$brandId = $service->brand->id;
$question = Question::findOrFail($this->question);
$questionTableName = (new Question())->getTable();
$answerTableName = (new Answer())->getTable();
return [
'question' => [
'required',
"exists:$questionTableName,id",
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) use ($question, $brandId) {
if ($question->brand->id !== $brandId) {
$fail("$attribute does not belong to brand $brandId");
}
}
],
'answers' => 'required|array',
'answers.*' => [
'int',
'distinct',
"exists:$answerTableName,id",
function ($attribute, $value, $fail) use ($question) {
if (Answer::findOrFail($value)->question->id !== $question->id) {
$fail("$attribute does not belong to question $question->id");
}
}
]
];
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources\Api\V2;
use App\Models\Answer;
use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
class AnswersResource extends JsonResourceCollection
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function toArray($request)
{
return $this->collection->map(function (Answer $answer) {
return [
'id' => $answer->id,
'answer' => $answer->answer
];
});
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace App\Http\Resources\Api\V2;
use App\Models\Question;
use Illuminate\Http\Resources\Json\JsonResource;
class QuestionResource extends JsonResource
{
/** @var Question */
private $question;
public function __construct(Question $question)
{
$this->question = $question;
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function toArray($request)
{
return [
'id' => $this->question->id,
'question' => $this->question->question,
'answers' => new AnswersResource($this->question->answers)
];
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace App\Http\Resources\Api\V2;
use App\Models\Question;
use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
use Illuminate\Support\Collection;
class QuestionsResource extends JsonResourceCollection
{
/** @var \Illuminate\Support\Collection */
protected $userAnwsers = null;
/**
* Create a new resource instance.
*
* @param mixed $resource
* @return void
*/
public function __construct($resource, Collection $userAnwsers = null)
{
$this->userAnwsers = $userAnwsers;
parent::__construct($resource);
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function toArray($request)
{
return $this->collection->map(function (Question $question) {
$question = [
'id' => $question->id,
'type' => $question->type->value,
'question' => $question->question,
'answers' => new AnswersResource($question->answers)
];
if ($this->userAnwsers) {
$question['customerAnswers'] = new AnswersResource($this->userAnwsers);
}
return $question;
});
}
}

View file

@ -24,12 +24,12 @@ class Answer extends Model
}
/**
* Answer hasOneThrough relation
* Answer belongsToMany relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function customer()
public function customers()
{
return $this->hasOneThrough(Customer::class, 'customer_answer');
return $this->belongsToMany(Customer::class, 'customer_answer');
}
}

View file

@ -23,6 +23,16 @@ class Brand extends Model
return $this->hasMany(Service::class);
}
/**
* Question hasMany relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function questions()
{
return $this->hasMany(Question::class);
}
/**
* CustomerInfo hasMany relation
*

View file

@ -84,6 +84,16 @@ class Customer extends Model
return $this->belongsToMany(Brand::class, CustomerInfo::class);
}
/**
* Answers belongsToMany relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function answers()
{
return $this->belongsToMany(Answer::class, 'customer_answer');
}
public function setOptIn(Brand $brand, bool $optIn)
{
// Ajout dans la table d'historique des opt-in de la nouvelle valeur

View file

@ -20,4 +20,14 @@ class CustomerOptInHistory extends Model
{
return $this->belongsTo(Customer::class);
}
/**
* Brand BelongsTo relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function brand()
{
return $this->belongsTo(Brand::class);
}
}

View file

@ -0,0 +1,17 @@
<?php
namespace App\Policies;
use App\Models\Customer;
use App\Models\Service;
use Illuminate\Auth\Access\HandlesAuthorization;
class CustomerPolicy
{
use HandlesAuthorization;
public function customerBelongsToService(Service $service, Customer $customer)
{
return $customer->login($service->brand)->exists();
}
}

View file

@ -52,6 +52,7 @@ class AuthServiceProvider extends ServiceProvider
try {
$service = Service::getFromApiToken($apiToken);
$service = $service->load('brand');
app()->bind(Service::class, function () use ($service) {
return $service;
});

@ -1 +1 @@
Subproject commit eb69ef30e9d2512d26c9f2718ef4d7d054dd766b
Subproject commit a336b3bfca10f6d383e585d68e80cc85b1b7295d

View file

@ -1,7 +1,7 @@
{
"name": "ldc/ldccrmv2client",
"type": "project",
"version": "2.0.0",
"version": "2.0.1",
"description": "LDC CRM V2",
"authors": [
{

View file

@ -2,8 +2,7 @@
namespace Database\Factories;
use App\Enums\QuestionType;
use App\Models\Question;
use App\Models\Answer;
use Illuminate\Database\Eloquent\Factories\Factory;
class AnswerFactory extends Factory
@ -14,7 +13,7 @@ class AnswerFactory extends Factory
*
* @var string
*/
protected $model = Question::class;
protected $model = Answer::class;
/**
* Define the model's default state.
@ -24,8 +23,7 @@ class AnswerFactory extends Factory
public function definition()
{
return [
'question' => $this->faker->name,
'type' => collect(QuestionType::toArray())->random()->value,
'answer' => $this->faker->realText(20),
];
}
}

View file

@ -24,7 +24,7 @@ class QuestionFactory extends Factory
public function definition()
{
return [
'question' => $this->faker->name,
'question' => $this->faker->realText(40),
'type' => collect(QuestionType::toArray())->random()->value,
];
}

View file

@ -14,7 +14,7 @@ class CreateCustomerAnswerTable extends Migration
public function up()
{
Schema::create('customer_answer', function (Blueprint $table) {
$table->foreignId('question_id')->constrained('questions');
$table->foreignId('answer_id')->constrained('answers');
$table->foreignId('customer_id')->constrained('customers');
$table->timestamp('created_at')->useCurrent();
});

View file

@ -2,7 +2,9 @@
namespace Database\Seeders;
use App\Models\Answer;
use App\Models\Brand;
use App\Models\Question;
use App\Models\Service;
use Illuminate\Database\Seeder;
@ -20,6 +22,14 @@ class BrandSeeder extends Seeder
Service::factory(1)->make()->each(
/** @var \App\Models\Service $service*/
function ($service) use ($brand) {
Question::factory(10)->make()->each(function ($question) use ($brand) {
$question->brand()->associate($brand);
$question->save();
Answer::factory(rand(3, 4))->make()->each(function ($answer) use ($question) {
$answer->question()->associate($question);
$answer->save();
});
});
$service->brand()->associate($brand);
$service->save();
}

View file

@ -7,6 +7,8 @@ use App\Http\Controllers\Api\V2\ApiController as V2ApiController;
use App\Http\Controllers\Api\V2\ArcadiaController as V2ArcadiaController;
use App\Http\Controllers\Api\V2\CustomerController as V2CustomerController;
use App\Http\Controllers\Api\V2\OptinController as V2OptinController;
use App\Http\Controllers\Api\V2\AnswerController as V2AnswerController;
use App\Http\Controllers\Api\V2\QuestionController as V2QuestionController;
/*
|--------------------------------------------------------------------------
@ -43,11 +45,13 @@ Route::prefix('v2')->name('apiV2.')->group(function () {
Route::post('/auth', [V2ApiController::class, 'authenticate'])->name('authenticate');
Route::middleware('auth:api')->group(function () {
Route::post('/optin', [V2OptinController::class, 'optin'])->name('optin');
Route::apiResource('customer', V2CustomerController::class)->except(['index']);
Route::prefix('customer')->name('customer.')->group(function () {
Route::apiResource('customers', V2CustomerController::class)->except(['index']);
Route::prefix('customers')->name('customers.')->group(function () {
Route::post('/authenticate', [V2CustomerController::class, 'authenticate'])->name('authenticate');
Route::prefix('{customer}')->group(function () {
Route::post('/activate', [V2CustomerController::class, 'activateAccount'])->name('activate');
Route::post('/answers', [V2AnswerController::class, 'storeCustomerAnswers'])
->name('answers.store');
});
});
Route::prefix('arcadia')->name('arcadia.')->group(function () {
@ -56,5 +60,12 @@ Route::prefix('v2')->name('apiV2.')->group(function () {
Route::post('/outgoing-mail/{customer}/game', [V2ArcadiaController::class, 'outgoingMailGame'])
->name('outgoingMailGame');
});
Route::apiResource('questions', V2QuestionController::class)->only(['index']);
Route::prefix('questions')->name('questions.')->group(function () {
Route::get('/un-answered-by/{customer}', [V2QuestionController::class, 'unAnsweredBy'])
->name('unAnsweredBy');
Route::get('/with-answers/{customer}', [V2QuestionController::class, 'indexWithResponse'])
->name('indexWithResponse');
});
});
});

View file

@ -69,12 +69,16 @@ class ApiBase extends BaseTestCase
* @param boolean $status the customer status for a brand
* @return array
*/
protected function getCustomer(bool $status = true): array
protected function getCustomer(bool $status = true, bool $random = true): array
{
/** @var \App\Models\Costumer $customer */
$customer = Customer::whereHas('logins', function ($q) use ($status) {
$q->where('status', $status);
})->inRandomOrder()->firstOrFail();
});
if ($random) {
$customer = $customer->inRandomOrder();
}
$customer = $customer->firstOrFail();
/** @var \App\Models\Login $login */
$login = $customer->logins()->where('status', $status)->firstOrFail();
/** @var \App\Models\Brand $brand */

View file

@ -14,7 +14,7 @@ class ArcadiaTest extends ApiBase
use DatabaseTransactions;
/**
* route: apiV2.customer.arcadia.outgoingMail
* route: apiV2.customers.arcadia.outgoingMail
*/
public function testArcadiaSendOrderDefault()
{

View file

@ -34,7 +34,7 @@ class CustomerTest extends ApiBase
}
/**
* route: apiV2.customer.authenticate
* route: apiV2.customers.authenticate
*/
public function testApiAuthenticateCustomer()
{
@ -42,7 +42,7 @@ class CustomerTest extends ApiBase
$response = $this->callApiWithToken(
$service,
'post',
route('apiV2.customer.authenticate', ['customer' => $info->hashcode]),
route('apiV2.customers.authenticate', ['customer' => $info->hashcode]),
[
'email' => $customer->email,
'password' => 'testPassword'
@ -65,7 +65,7 @@ class CustomerTest extends ApiBase
}
/**
* route: apiV2.customer.store
* route: apiV2.customers.store
*/
public function testApiStoreCustomer()
{
@ -83,7 +83,7 @@ class CustomerTest extends ApiBase
'postcode' => '72160',
'opt_in' => true
];
$response = $this->callApiWithToken($service, 'post', route('apiV2.customer.store'), $data);
$response = $this->callApiWithToken($service, 'post', route('apiV2.customers.store'), $data);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
@ -106,7 +106,7 @@ class CustomerTest extends ApiBase
$this->assertEquals($data['city'], $json->json('data.city'));
$this->assertEquals($data['postcode'], $json->json('data.postcode'));
$response = $this->callApiWithToken($service, 'post', route('apiV2.customer.store'), $data);
$response = $this->callApiWithToken($service, 'post', route('apiV2.customers.store'), $data);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO());
@ -115,28 +115,28 @@ class CustomerTest extends ApiBase
$data['password'] = 'password';
$response = $this->callApiWithToken($service, 'post', route('apiV2.customer.store'), $data);
$response = $this->callApiWithToken($service, 'post', route('apiV2.customers.store'), $data);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO());
$this->assertEquals(ApiError::validationFailed()->value, $json->json('data.code'));
}
/**
* route: apiV2.customer.activate
* route: apiV2.customers.activate
*/
public function testActivateCustomer()
{
extract($this->getCustomer(false));
$response = $this->callApiWithToken($service, 'post', route(
'apiV2.customer.activate',
'apiV2.customers.activate',
['customer' => $info->hashcode]
), []);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
$response = $this->callApiWithToken($service, 'post', route(
'apiV2.customer.activate',
'apiV2.customers.activate',
['customer' => $info->hashcode]
), []);
$json = $response->decodeResponseJson();
@ -146,7 +146,7 @@ class CustomerTest extends ApiBase
}
/**
* route: apiV2.customer.update
* route: apiV2.customers.update
*/
public function testApiUpdateCustomer()
{
@ -167,7 +167,7 @@ class CustomerTest extends ApiBase
foreach ($data as $rowName => $row) {
$response = $this->callApiWithToken($service, 'patch', route(
'apiV2.customer.update',
'apiV2.customers.update',
['customer' => $info->hashcode]
), [$rowName => $row]);
$json = $response->decodeResponseJson();
@ -189,7 +189,7 @@ class CustomerTest extends ApiBase
}
}
$response = $this->callApiWithToken($service, 'patch', route(
'apiV2.customer.update',
'apiV2.customers.update',
['customer' => $info->hashcode]
), ['address2' => 'anything']);
$json = $response->decodeResponseJson();
@ -198,14 +198,14 @@ class CustomerTest extends ApiBase
}
/**
* route: apiV2.customer.show
* route: apiV2.customers.show
*/
public function testApiGetCustomer()
{
extract($this->getCustomer());
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.customer.show',
'apiV2.customers.show',
['customer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
@ -226,7 +226,7 @@ class CustomerTest extends ApiBase
$uuid = Str::uuid();
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.customer.show',
'apiV2.customers.show',
['customer' => $uuid]
));
$json = $response->decodeResponseJson();
@ -252,7 +252,7 @@ class CustomerTest extends ApiBase
extract($this->getCustomer());
$service = $brand->services()->firstOrFail();
$response = $this->callApiWithToken($service, 'delete', route(
'apiV2.customer.destroy',
'apiV2.customers.destroy',
['customer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
@ -260,7 +260,7 @@ class CustomerTest extends ApiBase
$this->assertEmpty($json->json('data'));
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.customer.show',
'apiV2.customers.show',
['customer' => $info->hashcode]
));
$json = $response->decodeResponseJson();

View file

@ -0,0 +1,72 @@
<?php
namespace Tests\Feature\ApiV2;
use App\Enums\ApiStatus;
use App\Models\Question;
class QuestionTest extends ApiBase
{
/**
* route: apiV2.questions.index
*/
public function testQuestionIndex()
{
extract($this->getCustomer());
$response = $this->callApiWithToken($service, 'get', route('apiV2.questions.index'));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
}
/**
* route: apiV2.questions.indexWithResponse
*/
public function testQuestionIndexWithAnswers()
{
extract($this->getCustomer(true, false));
$service = $brand->services()->firstOrFail();
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.indexWithResponse',
['customer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
}
/**
* route: apiV2.questions.unAnsweredBy
*/
public function testCustomerUnAnsweredIndex()
{
extract($this->getCustomer());
$service = $brand->services()->firstOrFail();
$response = $this->callApiWithToken($service, 'get', route(
'apiV2.questions.unAnsweredBy',
['customer' => $info->hashcode]
));
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
}
/**
* route: apiV2.customers.answers.store
*/
public function testQuestionSetAnswer()
{
extract($this->getCustomer(true, false));
$question = Question::whereHas('brand', function ($q) use ($brand) {
$q->whereId($brand->id);
})->inRandomOrder()->firstOrFail();
$answer = $question->answers->first();
$response = $this->callApiWithToken($service, 'post', route('apiV2.customers.answers.store', [
'customer' => $info->hashcode
]), [
'question' => $question->id,
'answers' => [$answer->id]
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK());
}
}

View file

@ -68,6 +68,6 @@ class SingleOptinTest extends ApiBase
'postcode' => '72160',
'opt_in' => true
];
$this->callApiWithToken($service, 'post', route('apiV2.customer.store'), $data);
$this->callApiWithToken($service, 'post', route('apiV2.customers.store'), $data);
}
}

View file

@ -251,11 +251,11 @@ class CrmClientV2CustomerTest extends CrmClientTester
public function testCustomerDelete()
{
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$customer = $api->getCustomer('toto.delarogerie@gmail.com');
$this->assertTrue($customer->delete());
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$customer = $api->getCustomerOrNew('toto.delarogerie@gmail.com');
$this->assertEquals(null, $customer->hashcode);
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace Tests\Unit;
use Exception;
use LDC\LDCCRM\CrmApiV2;
use LDC\LDCCRM\Models\Answer;
use LDC\LDCCRM\Models\Question;
class CrmClientV2QuestionTest extends CrmClientTester
{
public function testGetAllQuestions()
{
$questions = Question::all();
$this->assertNotEmpty($questions, 'Should have returned some questions');
}
public function testGetAllQuestionsWithCustomerAnswers()
{
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$questions = Question::allWithCustomerAnswers($customer);
$this->assertNotEmpty($questions, 'Should have returned some questions');
}
public function testGetAllCustomerUnAnsweredQuestions()
{
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$questions = Question::unansweredBy($customer);
$this->assertNotEmpty($questions, 'Should have returned some questions');
}
public function testSubmitCustomerAnswer()
{
$questions = Question::all();
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$result = Answer::setQuestionAnswers(
$customer->hashcode,
$questions[0]->id,
[
$questions[0]->answers[0]->id,
$questions[0]->answers[1]->id
]
);
$this->assertTrue($result);
}
public function testGetAllCustomerUnansweredQuestionsShouldNotContainFirst()
{
$this->expectNotToPerformAssertions();
$unWantedQuestion = Question::all()[0];
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$questions = Question::unansweredBy($customer);
foreach ($questions as $question) {
if ($unWantedQuestion->id === $question->id) {
throw new Exception('The question should not appear');
}
}
}
public function testGetAllQuestionsWithCustomerAnswersShouldHaveAnswers()
{
$api = new CrmApiV2();
$customer = $api->getCustomerOrNew(static::$info->hashcode);
$questions = Question::allWithCustomerAnswers($customer);
$this->assertNotEmpty($questions[0]['customerAnswers'], 'Should have customer answers');
}
}

View file

@ -36,6 +36,12 @@ class CrmClientV2RouterTest extends CrmClientTester
if (\strpos($route['uri'], '{customer}') !== false) {
$query['customer'] = 1;
}
if (\strpos($route['uri'], '{question}') !== false) {
$query['question'] = 1;
}
if (\strpos($route['uri'], '{answer}') !== false) {
$query['answer'] = 1;
}
$request = Utils::getResquest($name, $query, $data);
$request->uri;
$request->method;