feat: translation codes
This commit is contained in:
@@ -25,7 +25,7 @@ class ReviewIdentityVerification
|
|||||||
abort_if(
|
abort_if(
|
||||||
$status === IdentityVerificationStatus::REJECTED && blank($rejectionReason),
|
$status === IdentityVerificationStatus::REJECTED && blank($rejectionReason),
|
||||||
422,
|
422,
|
||||||
__('api.certification.rejection_reason_required'),
|
'CERTIFICATION_REJECTION_REASON_REQUIRED',
|
||||||
);
|
);
|
||||||
|
|
||||||
$reviewedRequest = DB::transaction(function () use (
|
$reviewedRequest = DB::transaction(function () use (
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class SubmitIdentityVerification
|
|||||||
$existingRequest = $user->identityVerificationRequest()->first();
|
$existingRequest = $user->identityVerificationRequest()->first();
|
||||||
|
|
||||||
if ($existingRequest?->status === IdentityVerificationStatus::PENDING) {
|
if ($existingRequest?->status === IdentityVerificationStatus::PENDING) {
|
||||||
throw new ConflictHttpException(__('api.certification.already_pending'));
|
throw new ConflictHttpException('CERTIFICATION_ALREADY_PENDING');
|
||||||
}
|
}
|
||||||
|
|
||||||
$disk = (string) config('billing.identity_verification.disk', 'identity_documents');
|
$disk = (string) config('billing.identity_verification.disk', 'identity_documents');
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ class DeviceTokenController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $deviceToken->wasRecentlyCreated
|
'code' => $deviceToken->wasRecentlyCreated
|
||||||
? __('api.device_tokens.created')
|
? 'DEVICE_TOKEN_CREATED'
|
||||||
: __('api.device_tokens.updated'),
|
: 'DEVICE_TOKEN_UPDATED',
|
||||||
'deviceToken' => [
|
'deviceToken' => [
|
||||||
'id' => $deviceToken->id,
|
'id' => $deviceToken->id,
|
||||||
'expoPushToken' => $deviceToken->expo_push_token,
|
'expoPushToken' => $deviceToken->expo_push_token,
|
||||||
@@ -40,7 +40,7 @@ class DeviceTokenController extends Controller
|
|||||||
auth()->user()->notify(new TestNotification);
|
auth()->user()->notify(new TestNotification);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.device_tokens.notification_sent'),
|
'code' => 'TEST_NOTIFICATION_SENT',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class FollowController extends Controller
|
|||||||
|
|
||||||
if ($authUser->id === $user->id) {
|
if ($authUser->id === $user->id) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.follows.cannot_follow_self'),
|
'code' => 'CANNOT_FOLLOW_SELF',
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class FollowController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.follows.followed'),
|
'code' => 'USER_FOLLOWED',
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ class FollowController extends Controller
|
|||||||
$request->user()->following()->detach($user->id);
|
$request->user()->following()->detach($user->id);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.follows.unfollowed'),
|
'code' => 'USER_UNFOLLOWED',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class FollowController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $updated ? __('api.follows.accepted') : __('api.follows.not_found'),
|
'code' => $updated ? 'FOLLOW_REQUEST_ACCEPTED' : 'FOLLOW_REQUEST_NOT_FOUND',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ class FollowController extends Controller
|
|||||||
$detached = $request->user()->followers()->detach($user->id);
|
$detached = $request->user()->followers()->detach($user->id);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $detached ? __('api.follows.rejected') : __('api.follows.not_found'),
|
'code' => $detached ? 'FOLLOW_REQUEST_REJECTED' : 'FOLLOW_REQUEST_NOT_FOUND',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class LegalDocumentController extends Controller
|
|||||||
{
|
{
|
||||||
$document = LegalDocument::publicForSlug($slug);
|
$document = LegalDocument::publicForSlug($slug);
|
||||||
|
|
||||||
abort_if(! $document, 404, __('api.legal_documents.not_found'));
|
abort_if(! $document, 404, 'LEGAL_DOCUMENT_NOT_FOUND');
|
||||||
|
|
||||||
return new LegalDocumentResource($document);
|
return new LegalDocumentResource($document);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class MealImageAnalysisController extends Controller
|
|||||||
|
|
||||||
if (! $user->canAnalyzeMeals()) {
|
if (! $user->canAnalyzeMeals()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.meal_image_analysis.subscription_required'),
|
'code' => 'MEAL_ANALYSIS_SUBSCRIPTION_REQUIRED',
|
||||||
], 402);
|
], 402);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ class MealImageAnalysisController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.meal_image_analysis.failed'),
|
'code' => 'MEAL_ANALYSIS_FAILED',
|
||||||
], 502);
|
], 502);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class NotificationController extends Controller
|
|||||||
'data' => [
|
'data' => [
|
||||||
'updated' => $updated,
|
'updated' => $updated,
|
||||||
],
|
],
|
||||||
'message' => __('api.notifications.all_read'),
|
'code' => 'NOTIFICATIONS_MARKED_AS_READ',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class NotificationPreferenceController extends Controller
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => $this->preferences($request),
|
'data' => $this->preferences($request),
|
||||||
'message' => __('api.notifications.preferences_updated'),
|
'code' => 'NOTIFICATION_PREFERENCES_UPDATED',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class PostReviewsController extends Controller
|
|||||||
->where('user_id', $userId)
|
->where('user_id', $userId)
|
||||||
->exists(),
|
->exists(),
|
||||||
409,
|
409,
|
||||||
__('api.post_reviews.already_exists')
|
'MEAL_REVIEW_ALREADY_EXISTS'
|
||||||
);
|
);
|
||||||
|
|
||||||
$postReview = PostReviews::create([
|
$postReview = PostReviews::create([
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class ReportController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (new ReportResource($report))
|
return (new ReportResource($report))
|
||||||
->additional(['message' => __('api.reports.created')])
|
->additional(['code' => 'REPORT_CREATED'])
|
||||||
->response()
|
->response()
|
||||||
->setStatusCode(201);
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ class ReportController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (new ReportResource($report))
|
return (new ReportResource($report))
|
||||||
->additional(['message' => __('api.reports.created')])
|
->additional(['code' => 'REPORT_CREATED'])
|
||||||
->response()
|
->response()
|
||||||
->setStatusCode(201);
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ class ReportController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (new ReportResource($report))
|
return (new ReportResource($report))
|
||||||
->additional(['message' => __('api.reports.created')])
|
->additional(['code' => 'REPORT_CREATED'])
|
||||||
->response()
|
->response()
|
||||||
->setStatusCode(201);
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ class StravaController extends Controller
|
|||||||
|
|
||||||
if (! is_array($state) || $state['user_id'] !== $request->user()->getKey()) {
|
if (! is_array($state) || $state['user_id'] !== $request->user()->getKey()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.state_expired'),
|
'code' => 'STRAVA_STATE_EXPIRED',
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['error'])) {
|
if (isset($data['error'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.refused'),
|
'code' => 'STRAVA_AUTHORIZATION_REFUSED',
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,14 +115,14 @@ class StravaController extends Controller
|
|||||||
report($exception);
|
report($exception);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.disconnect_failed'),
|
'code' => 'STRAVA_DISCONNECT_FAILED',
|
||||||
], 502);
|
], 502);
|
||||||
}
|
}
|
||||||
} catch (ConnectionException $exception) {
|
} catch (ConnectionException $exception) {
|
||||||
report($exception);
|
report($exception);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.disconnect_failed'),
|
'code' => 'STRAVA_DISCONNECT_FAILED',
|
||||||
], 502);
|
], 502);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,13 +137,13 @@ class StravaController extends Controller
|
|||||||
|
|
||||||
if (! $connection) {
|
if (! $connection) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.missing_connection'),
|
'code' => 'STRAVA_CONNECTION_MISSING',
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->canReadActivities($connection->scopes ?? [])) {
|
if (! $this->canReadActivities($connection->scopes ?? [])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.strava.missing_activity_scope'),
|
'code' => 'STRAVA_ACTIVITY_SCOPE_MISSING',
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ class UserBlockController extends Controller
|
|||||||
|
|
||||||
public function store(Request $request, User $user, BlockUser $blockUser): JsonResponse
|
public function store(Request $request, User $user, BlockUser $blockUser): JsonResponse
|
||||||
{
|
{
|
||||||
abort_if($request->user()->is($user), 422, __('api.blocks.cannot_block_self'));
|
abort_if($request->user()->is($user), 422, 'CANNOT_BLOCK_SELF');
|
||||||
|
|
||||||
$blockUser->execute($request->user(), $user);
|
$blockUser->execute($request->user(), $user);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.blocks.blocked'),
|
'code' => 'USER_BLOCKED',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class EnsureAccountIsNotSuspended
|
|||||||
{
|
{
|
||||||
if ($request->user()?->isSuspended()) {
|
if ($request->user()?->isSuspended()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('api.auth.suspended'),
|
'code' => 'ACCOUNT_SUSPENDED',
|
||||||
], 403);
|
], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class EnsureEmailIsVerified
|
|||||||
($request->user() instanceof MustVerifyEmail &&
|
($request->user() instanceof MustVerifyEmail &&
|
||||||
! $request->user()->hasVerifiedEmail())) {
|
! $request->user()->hasVerifiedEmail())) {
|
||||||
return $request->expectsJson()
|
return $request->expectsJson()
|
||||||
? abort(403, __('api.auth.email_not_verified'))
|
? abort(403, 'EMAIL_NOT_VERIFIED')
|
||||||
: Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));
|
: Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ class LegalDocumentResource extends JsonResource
|
|||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'slug' => $this->slug,
|
'slug' => $this->slug,
|
||||||
'type' => $this->type?->value,
|
'type' => $this->type?->value,
|
||||||
'typeLabel' => $this->type?->getLabel(),
|
|
||||||
'version' => $this->version,
|
'version' => $this->version,
|
||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'content' => $this->content,
|
'content' => $this->content,
|
||||||
|
|||||||
@@ -17,10 +17,8 @@ class ReportResource extends JsonResource
|
|||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'reason' => $this->reason,
|
'reason' => $this->reason,
|
||||||
'reasonLabel' => $this->reason?->getLabel(),
|
|
||||||
'details' => $this->details,
|
'details' => $this->details,
|
||||||
'status' => $this->status,
|
'status' => $this->status,
|
||||||
'statusLabel' => $this->status?->getLabel(),
|
|
||||||
'reportableType' => $this->reportableType(),
|
'reportableType' => $this->reportableType(),
|
||||||
'reportableId' => $this->reportable_id,
|
'reportableId' => $this->reportable_id,
|
||||||
'moderationCaseId' => $this->moderation_case_id,
|
'moderationCaseId' => $this->moderation_case_id,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class ContentModerationService
|
|||||||
$apiKey = trim((string) config('moderation.content.openai_key'));
|
$apiKey = trim((string) config('moderation.content.openai_key'));
|
||||||
|
|
||||||
if ($apiKey === '') {
|
if ($apiKey === '') {
|
||||||
throw new HttpException(503, __('api.moderation.unavailable'));
|
throw new HttpException(503, 'CONTENT_MODERATION_UNAVAILABLE');
|
||||||
}
|
}
|
||||||
|
|
||||||
$input = [];
|
$input = [];
|
||||||
@@ -80,7 +80,7 @@ class ContentModerationService
|
|||||||
} catch (Throwable $exception) {
|
} catch (Throwable $exception) {
|
||||||
report($exception);
|
report($exception);
|
||||||
|
|
||||||
throw new HttpException(503, __('api.moderation.unavailable'), $exception);
|
throw new HttpException(503, 'CONTENT_MODERATION_UNAVAILABLE', $exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collect($response->json('results', []))->contains(
|
if (collect($response->json('results', []))->contains(
|
||||||
@@ -107,7 +107,7 @@ class ContentModerationService
|
|||||||
$contents = file_get_contents($image->getRealPath());
|
$contents = file_get_contents($image->getRealPath());
|
||||||
|
|
||||||
if ($contents === false) {
|
if ($contents === false) {
|
||||||
throw new HttpException(503, __('api.moderation.unavailable'));
|
throw new HttpException(503, 'CONTENT_MODERATION_UNAVAILABLE');
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
@@ -126,7 +126,7 @@ class ContentModerationService
|
|||||||
private function rejectContent(): never
|
private function rejectContent(): never
|
||||||
{
|
{
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'content' => [__('api.moderation.rejected')],
|
'content' => ['CONTENT_MODERATION_REJECTED'],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class ModerationReportService
|
|||||||
->where('reportable_id', $reportable->getKey())
|
->where('reportable_id', $reportable->getKey())
|
||||||
->exists(),
|
->exists(),
|
||||||
409,
|
409,
|
||||||
__('api.reports.already_exists'),
|
'REPORT_ALREADY_EXISTS',
|
||||||
);
|
);
|
||||||
|
|
||||||
$report = Report::create([
|
$report = Report::create([
|
||||||
@@ -62,7 +62,7 @@ class ModerationReportService
|
|||||||
});
|
});
|
||||||
} catch (QueryException $exception) {
|
} catch (QueryException $exception) {
|
||||||
if ($this->isDuplicateReportException($exception)) {
|
if ($this->isDuplicateReportException($exception)) {
|
||||||
abort(409, __('api.reports.already_exists'));
|
abort(409, 'REPORT_ALREADY_EXISTS');
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $exception;
|
throw $exception;
|
||||||
@@ -128,19 +128,19 @@ class ModerationReportService
|
|||||||
abort_if(
|
abort_if(
|
||||||
$reportable instanceof User && $reportable->is($reporter),
|
$reportable instanceof User && $reportable->is($reporter),
|
||||||
422,
|
422,
|
||||||
__('api.reports.cannot_report_self'),
|
'CANNOT_REPORT_SELF',
|
||||||
);
|
);
|
||||||
|
|
||||||
abort_if(
|
abort_if(
|
||||||
$reportable instanceof MealPosts && $reportable->user_id === $reporter->getKey(),
|
$reportable instanceof MealPosts && $reportable->user_id === $reporter->getKey(),
|
||||||
422,
|
422,
|
||||||
__('api.reports.cannot_report_own_meal'),
|
'CANNOT_REPORT_OWN_MEAL',
|
||||||
);
|
);
|
||||||
|
|
||||||
abort_if(
|
abort_if(
|
||||||
$reportable instanceof PostReviews && $reportable->user_id === $reporter->getKey(),
|
$reportable instanceof PostReviews && $reportable->user_id === $reporter->getKey(),
|
||||||
422,
|
422,
|
||||||
__('api.reports.cannot_report_own_review'),
|
'CANNOT_REPORT_OWN_REVIEW',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ it('deletes the authenticated account and related data', function () {
|
|||||||
|
|
||||||
$this->deleteJson('/api/auth/me')
|
$this->deleteJson('/api/auth/me')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.auth.deleted'));
|
->assertJsonPath('code', 'ACCOUNT_DELETED');
|
||||||
|
|
||||||
$this->assertDatabaseMissing('users', ['id' => $user->getKey()]);
|
$this->assertDatabaseMissing('users', ['id' => $user->getKey()]);
|
||||||
$this->assertDatabaseMissing('meal_posts', ['id' => $localMealPost->getKey()]);
|
$this->assertDatabaseMissing('meal_posts', ['id' => $localMealPost->getKey()]);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ it('prevents replacing a document while it is under review', function () {
|
|||||||
'document' => UploadedFile::fake()->image('identity.jpg'),
|
'document' => UploadedFile::fake()->image('identity.jpg'),
|
||||||
])
|
])
|
||||||
->assertConflict()
|
->assertConflict()
|
||||||
->assertJsonPath('message', __('api.certification.already_pending'));
|
->assertJsonPath('code', 'CERTIFICATION_ALREADY_PENDING');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('approves a certification and removes the reviewed identity document', function () {
|
it('approves a certification and removes the reviewed identity document', function () {
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ it('fails closed when production moderation cannot be reached', function () {
|
|||||||
'comment' => 'Très bon repas.',
|
'comment' => 'Très bon repas.',
|
||||||
])
|
])
|
||||||
->assertServiceUnavailable()
|
->assertServiceUnavailable()
|
||||||
->assertJsonPath('message', __('api.moderation.unavailable'));
|
->assertJsonPath('code', 'CONTENT_MODERATION_UNAVAILABLE');
|
||||||
|
|
||||||
$this->assertDatabaseCount('post_reviews', 0);
|
$this->assertDatabaseCount('post_reviews', 0);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ it('records a failed meal image analysis attempt', function () {
|
|||||||
'image' => fakeMealAnalysisImage(),
|
'image' => fakeMealAnalysisImage(),
|
||||||
])
|
])
|
||||||
->assertStatus(502)
|
->assertStatus(502)
|
||||||
->assertJsonPath('message', __('api.meal_image_analysis.failed'));
|
->assertJsonPath('code', 'MEAL_ANALYSIS_FAILED');
|
||||||
|
|
||||||
Exceptions::assertReported(\RuntimeException::class);
|
Exceptions::assertReported(\RuntimeException::class);
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ it('requires an active subscription to analyze a meal image', function () {
|
|||||||
'image' => fakeMealAnalysisImage(),
|
'image' => fakeMealAnalysisImage(),
|
||||||
])
|
])
|
||||||
->assertStatus(402)
|
->assertStatus(402)
|
||||||
->assertJsonPath('message', __('api.meal_image_analysis.subscription_required'));
|
->assertJsonPath('code', 'MEAL_ANALYSIS_SUBSCRIPTION_REQUIRED');
|
||||||
|
|
||||||
expect(AiUsage::query()->count())->toBe(0);
|
expect(AiUsage::query()->count())->toBe(0);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ it('creates a report and a moderation case for a meal post', function () {
|
|||||||
'details' => 'Même image publiée en boucle.',
|
'details' => 'Même image publiée en boucle.',
|
||||||
])
|
])
|
||||||
->assertCreated()
|
->assertCreated()
|
||||||
->assertJsonPath('message', __('api.reports.created'))
|
->assertJsonPath('code', 'REPORT_CREATED')
|
||||||
->assertJsonPath('data.reason', ReportReason::SPAM->value)
|
->assertJsonPath('data.reason', ReportReason::SPAM->value)
|
||||||
->assertJsonPath('data.reportableType', 'meal_post')
|
->assertJsonPath('data.reportableType', 'meal_post')
|
||||||
->assertJsonPath('data.reportableId', $mealPost->id);
|
->assertJsonPath('data.reportableId', $mealPost->id);
|
||||||
@@ -58,7 +58,7 @@ it('prevents duplicate reports and reports on own content', function () {
|
|||||||
|
|
||||||
$this->postJson("/api/meal-posts/{$mealPost->id}/reports", $payload)
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reports", $payload)
|
||||||
->assertConflict()
|
->assertConflict()
|
||||||
->assertJsonPath('message', __('api.reports.already_exists'));
|
->assertJsonPath('code', 'REPORT_ALREADY_EXISTS');
|
||||||
|
|
||||||
expect(Report::query()->count())->toBe(1);
|
expect(Report::query()->count())->toBe(1);
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ it('prevents duplicate reports and reports on own content', function () {
|
|||||||
|
|
||||||
$this->postJson("/api/meal-posts/{$mealPost->id}/reports", $payload)
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reports", $payload)
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('api.reports.cannot_report_own_meal'));
|
->assertJsonPath('code', 'CANNOT_REPORT_OWN_MEAL');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reports users and prevents reporting own profile', function () {
|
it('reports users and prevents reporting own profile', function () {
|
||||||
@@ -94,7 +94,7 @@ it('reports users and prevents reporting own profile', function () {
|
|||||||
'reason' => ReportReason::OTHER->value,
|
'reason' => ReportReason::OTHER->value,
|
||||||
])
|
])
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('api.reports.cannot_report_self'));
|
->assertJsonPath('code', 'CANNOT_REPORT_SELF');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reports post reviews and prevents reporting own review', function () {
|
it('reports post reviews and prevents reporting own review', function () {
|
||||||
@@ -128,7 +128,7 @@ it('reports post reviews and prevents reporting own review', function () {
|
|||||||
'reason' => ReportReason::OTHER->value,
|
'reason' => ReportReason::OTHER->value,
|
||||||
])
|
])
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('api.reports.cannot_report_own_review'));
|
->assertJsonPath('code', 'CANNOT_REPORT_OWN_REVIEW');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('notifies moderators once when a report threshold is reached', function () {
|
it('notifies moderators once when a report threshold is reached', function () {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ it('sends a password reset email with a clickable api web url', function () {
|
|||||||
'email' => 'LEON@example.com',
|
'email' => 'LEON@example.com',
|
||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.auth.password_reset_link_sent'));
|
->assertJsonPath('code', 'PASSWORD_RESET_LINK_SENT');
|
||||||
|
|
||||||
Notification::assertSentTo(
|
Notification::assertSentTo(
|
||||||
$user,
|
$user,
|
||||||
@@ -99,7 +99,7 @@ it('does not reveal whether a reset email can be sent', function () {
|
|||||||
'email' => 'missing@example.com',
|
'email' => 'missing@example.com',
|
||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.auth.password_reset_link_sent'));
|
->assertJsonPath('code', 'PASSWORD_RESET_LINK_SENT');
|
||||||
|
|
||||||
Notification::assertNothingSent();
|
Notification::assertNothingSent();
|
||||||
});
|
});
|
||||||
@@ -121,7 +121,7 @@ it('resets the password and invalidates existing api tokens', function () {
|
|||||||
'token' => $token,
|
'token' => $token,
|
||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.auth.password_reset'));
|
->assertJsonPath('code', 'PASSWORD_RESET');
|
||||||
|
|
||||||
expect(Hash::check('new-password', $user->fresh()->password))->toBeTrue();
|
expect(Hash::check('new-password', $user->fresh()->password))->toBeTrue();
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ it('rejects an invalid password reset token', function () {
|
|||||||
'token' => 'invalid-token',
|
'token' => 'invalid-token',
|
||||||
])
|
])
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('passwords.token'));
|
->assertJsonPath('code', 'PASSWORD_RESET_FAILED');
|
||||||
|
|
||||||
expect(Hash::check('new-password', $user->fresh()->password))->toBeFalse();
|
expect(Hash::check('new-password', $user->fresh()->password))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ it('creates one review per user for a meal post', function () {
|
|||||||
'rating' => 4,
|
'rating' => 4,
|
||||||
])
|
])
|
||||||
->assertConflict()
|
->assertConflict()
|
||||||
->assertJsonPath('message', __('api.post_reviews.already_exists'));
|
->assertJsonPath('code', 'MEAL_REVIEW_ALREADY_EXISTS');
|
||||||
|
|
||||||
expect(PostReviews::query()->count())->toBe(1);
|
expect(PostReviews::query()->count())->toBe(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ it('keeps the local strava connection when strava revocation fails temporarily',
|
|||||||
$this
|
$this
|
||||||
->deleteJson('/api/strava/connection')
|
->deleteJson('/api/strava/connection')
|
||||||
->assertStatus(502)
|
->assertStatus(502)
|
||||||
->assertJsonPath('message', __('api.strava.disconnect_failed'));
|
->assertJsonPath('code', 'STRAVA_DISCONNECT_FAILED');
|
||||||
|
|
||||||
expect($user->fresh()->stravaConnection)->not->toBeNull();
|
expect($user->fresh()->stravaConnection)->not->toBeNull();
|
||||||
});
|
});
|
||||||
@@ -295,5 +295,5 @@ it('requires an activity read scope before syncing strava activities', function
|
|||||||
$this
|
$this
|
||||||
->postJson('/api/strava/sync')
|
->postJson('/api/strava/sync')
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('api.strava.missing_activity_scope'));
|
->assertJsonPath('code', 'STRAVA_ACTIVITY_SCOPE_MISSING');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ it('updates the authenticated user password and keeps the current api token', fu
|
|||||||
'passwordConfirmation' => 'NewPassword123!',
|
'passwordConfirmation' => 'NewPassword123!',
|
||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.auth.password_updated'));
|
->assertJsonPath('code', 'PASSWORD_UPDATED');
|
||||||
|
|
||||||
expect(Hash::check('NewPassword123!', $user->fresh()->password))->toBeTrue();
|
expect(Hash::check('NewPassword123!', $user->fresh()->password))->toBeTrue();
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ it('blocks a user idempotently, removes follows, lists the block, and unblocks',
|
|||||||
|
|
||||||
$this->postJson("/api/users/{$blocked->id}/block")
|
$this->postJson("/api/users/{$blocked->id}/block")
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('message', __('api.blocks.blocked'));
|
->assertJsonPath('code', 'USER_BLOCKED');
|
||||||
|
|
||||||
$this->postJson("/api/users/{$blocked->id}/block")->assertOk();
|
$this->postJson("/api/users/{$blocked->id}/block")->assertOk();
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ it('does not allow a user to block themselves', function () {
|
|||||||
|
|
||||||
$this->postJson("/api/users/{$user->id}/block")
|
$this->postJson("/api/users/{$user->id}/block")
|
||||||
->assertUnprocessable()
|
->assertUnprocessable()
|
||||||
->assertJsonPath('message', __('api.blocks.cannot_block_self'));
|
->assertJsonPath('code', 'CANNOT_BLOCK_SELF');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('requires authentication to manage blocks', function () {
|
it('requires authentication to manage blocks', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user