Skip to content

Commit

Permalink
add question cloning
Browse files Browse the repository at this point in the history
  • Loading branch information
AmonDeShir committed Aug 12, 2024
1 parent 2163438 commit d189c2d
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 0 deletions.
12 changes: 12 additions & 0 deletions app/Http/Controllers/QuestionAnswerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,16 @@ public function destroy(Answer $answer): RedirectResponse
->back()
->with("success", "Answer deleted");
}

/**
* @throws AuthorizationException
*/
public function clone(Answer $answer, Question $question): RedirectResponse
{
$answer->cloneTo($question);

return redirect()
->back()
->with("success", "Answer cloned");
}
}
12 changes: 12 additions & 0 deletions app/Http/Controllers/QuizQuestionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,16 @@ public function destroy(Question $question): RedirectResponse
->back()
->with("success", "Question deleted");
}

/**
* @throws AuthorizationException
*/
public function clone(Question $question, Quiz $quiz): RedirectResponse
{
$question->cloneTo($quiz);

return redirect()
->back()
->with("success", "Question cloned");
}
}
26 changes: 26 additions & 0 deletions app/Models/Question.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Models;

use Carbon\Carbon;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
Expand Down Expand Up @@ -53,4 +54,29 @@ public function isLocked(): Attribute
{
return Attribute::get(fn(): bool => $this->quiz->isLocked);
}

/**
* @throws AuthorizationException
*/
public function cloneTo(Quiz $quiz): self
{
if ($quiz->isLocked) {
throw new AuthorizationException();
}

$questionCopy = $this->replicate();
$questionCopy->quiz()->associate($quiz)->save();

foreach ($this->answers as $answer) {
$answerCopy = $answer->cloneTo($questionCopy);

if ($answer->isCorrect) {
$questionCopy->correctAnswer()->associate($answerCopy);
}
}

$questionCopy->save();

return $questionCopy;
}
}
1 change: 1 addition & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Route::get("/", fn(): Response => inertia("Welcome"));

Route::post("/quizzes/{quiz}/lock", [QuizController::class, "lock"]);
Route::post("/questions/{question}/clone/{quiz}", [QuizQuestionController::class, "clone"]);
Route::post("/answers/{answer}/correct", [QuestionAnswerController::class, "markAsCorrect"]);
Route::post("/answers/{answer}/invalid", [QuestionAnswerController::class, "markAsInvalid"]);
Route::post("/answers/{answer}/clone/{question}", [QuestionAnswerController::class, "clone"]);
Expand Down
97 changes: 97 additions & 0 deletions tests/Feature/QuestionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,101 @@ public function testUserCannotDeleteQuestionThatNotExisted(): void
->delete("/questions/1")
->assertStatus(404);
}

public function testUserCanCopyQuestion(): void
{
$user = User::factory()->create();
$quizA = Quiz::factory()->create();
$quizB = Quiz::factory()->create();
$question = Question::factory()->create(["quiz_id" => $quizA->id]);
Answer::factory()->count(10)->create(["question_id" => $question->id]);

$this->assertDatabaseHas("questions", ["quiz_id" => $quizA->id]);
$this->assertDatabaseCount("answers", 10);

$this->actingAs($user)
->from("/quizzes")
->post("/questions/{$question->id}/clone/{$quizB->id}")
->assertRedirect("/quizzes");

$this->assertDatabaseHas("questions", ["quiz_id" => $quizB->id]);
$this->assertDatabaseCount("answers", 20);
}

public function testUserCanCopyLockedQuestion(): void
{
$user = User::factory()->create();
$quizA = Quiz::factory()->locked()->create();
$quizB = Quiz::factory()->create();
$question = Question::factory()->create(["quiz_id" => $quizA->id]);

$this->assertDatabaseHas("questions", ["quiz_id" => $quizA->id]);

$this->actingAs($user)
->from("/quizzes")
->post("/questions/{$question->id}/clone/{$quizB->id}")
->assertRedirect("/quizzes");

$this->assertDatabaseHas("questions", ["quiz_id" => $quizB->id]);
}

public function testUserCannotCopyAnswerToLockedQuestion(): void
{
$user = User::factory()->create();
$quizA = Quiz::factory()->create();
$quizB = Quiz::factory()->locked()->create();
$question = Question::factory()->create(["quiz_id" => $quizA->id]);

$this->assertDatabaseHas("questions", ["quiz_id" => $quizA->id]);

$this->actingAs($user)
->from("/quizzes")
->post("/questions/{$question->id}/clone/{$quizB->id}")
->assertStatus(403);

$this->assertDatabaseHas("questions", ["quiz_id" => $quizA->id]);
}

public function testUserCanCopyQuestionWithCorrectAnswer(): void
{
$user = User::factory()->create();
$quizA = Quiz::factory()->create();
$quizB = Quiz::factory()->create();
$question = Question::factory()->create(["quiz_id" => $quizA->id]);
$answer = Answer::factory()->create(["text" => "correct", "question_id" => $question->id]);

$question->correctAnswer()->associate($answer);
$question->save();

$this->actingAs($user)
->from("/quizzes")
->post("/questions/{$question->id}/clone/{$quizB->id}")
->assertRedirect("/quizzes");

$this->assertNotNull($quizA->questions[0]->correctAnswer);
$this->assertNotNull($quizB->questions[0]->correctAnswer);
$this->assertNotEquals($quizA->questions[0]->correctAnswer->id, $quizB->questions[0]->correctAnswer->id);
}

public function testUserCannotCopyQuestionThatNotExisted(): void
{
$user = User::factory()->create();
$quiz = Question::factory()->create();

$this->actingAs($user)
->from("/quizzes")
->post("/questions/2/clone/{$quiz->id}")
->assertStatus(404);
}

public function testUserCannotCopyAnswerToQuestionThatNotExisted(): void
{
$user = User::factory()->create();
$question = Question::factory()->create();

$this->actingAs($user)
->from("/quizzes")
->post("/questions/{$question->id}/clone/2")
->assertStatus(404);
}
}

0 comments on commit d189c2d

Please sign in to comment.