Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/testing v9 #51

Merged
merged 3 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ jobs:
uses: josecfreittas/elixir-coverage-feedback-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
coverage_threshold: 70
coverage_threshold: 80
services:
pg:
image: postgres:16
Expand Down
1 change: 0 additions & 1 deletion apps/core/lib/core/gcp/manager.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ defmodule GoEscuelaLms.Core.GCP.Manager do

def connection() do
{:ok, token} = Goth.fetch(Core.Goth)
IO.puts("connection ==> #{inspect(token)}")
GoogleApi.Storage.V1.Connection.new(token.token)
end

Expand Down
2 changes: 0 additions & 2 deletions apps/core/lib/core/schema/question.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ defmodule GoEscuelaLms.Core.Schema.Question do
end

def bulk_create(activity, records) do
IO.puts("RECORDS ===> #{inspect(records)}")

Repo.transaction(fn ->
Enum.each(records, fn record ->
question =
Expand Down
1 change: 1 addition & 0 deletions apps/core/lib/core/schema/topic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ defmodule GoEscuelaLms.Core.Schema.Topic do

def find(uuid) do
Repo.get(Topic, uuid)
|> Repo.preload(:course)
|> Repo.preload(:activities)
end

Expand Down
5 changes: 4 additions & 1 deletion apps/core/test/core/schema/topic_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ defmodule Core.TopicTest do

describe "find/1" do
test "when exist", %{course: course} do
topic = insert!(:topic, course_id: course.uuid) |> Repo.preload(:activities)
topic =
insert!(:topic, course_id: course.uuid)
|> Repo.preload(:course)
|> Repo.preload(:activities)

assert Topic.find(topic.uuid) == topic
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ defmodule Web.Activities.ActivitiesController do
}

def create(conn, params) do
topic = conn.assigns.topic
topic = conn.assigns.object

with {:ok, valid_params} <- Tarams.cast(params, @create_params),
{:ok, valid_params} <- activity_type_valid_params(params, valid_params),
Expand Down
8 changes: 4 additions & 4 deletions apps/web/lib/web/controllers/topics/topics_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ defmodule Web.Topics.TopicsController do

alias GoEscuelaLms.Core.Schema.Topic

plug :permit_authorized when action in [:create]
plug :permit_authorized when action in [:create, :update, :delete]
plug :load_course when action in [:create]
plug :check_enrollment when action in [:create]
plug :load_topic when action in [:update, :delete]
plug :check_enrollment when action in [:create, :update, :delete]

@create_params %{
name: [type: :string, required: true]
Expand All @@ -27,7 +27,7 @@ defmodule Web.Topics.TopicsController do
end

def update(conn, params) do
topic = conn.assigns.topic
topic = conn.assigns.object

with {:ok, valid_params} <- Tarams.cast(params, @create_params),
{:ok, topic_updated} <- update_topic(topic, valid_params) do
Expand All @@ -36,7 +36,7 @@ defmodule Web.Topics.TopicsController do
end

def delete(conn, _params) do
topic = conn.assigns.topic
topic = conn.assigns.object

case topic |> Topic.delete() do
{:ok, topic} ->
Expand Down
2 changes: 1 addition & 1 deletion apps/web/lib/web/controllers/users/users_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Web.Users.UsersController do

alias GoEscuelaLms.Core.Schema.User

plug :organizer_authorized when action in [:create]
plug :organizer_authorized when action in [:create, :index]
plug :load_user when action in [:update, :delete]

@create_params %{
Expand Down
4 changes: 3 additions & 1 deletion apps/web/lib/web/controllers/users/users_json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ defmodule Web.Users.UsersJSON do
%{
id: user.uuid,
email: user.email,
full_name: user.full_name
role: user.role,
full_name: user.full_name,
inserted_at: user.inserted_at |> to_string()
}
end
end
12 changes: 7 additions & 5 deletions apps/web/lib/web/plug/check_request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule Web.Plug.CheckRequest do
with :ok <- valid_uuids(id),
object <- Topic.find(id),
false <- is_nil(object) do
assign(conn, :topic, object)
assign(conn, :object, object)
else
_ ->
Web.FallbackController.call(conn, {:error, "topic is invalid"}) |> halt()
Expand All @@ -61,12 +61,14 @@ defmodule Web.Plug.CheckRequest do
def check_enrollment(%{assigns: %{account: %{role: :organizer}}} = conn, _), do: conn

def check_enrollment(conn, _) do
user_id = conn.assigns.account.uuid
course = conn.assigns.course
account = conn.assigns.account
enrollments = account.enrollments

course = conn.assigns |> get_in([:course]) || conn.assigns.object.course

case is_nil(
course.enrollments
|> Enum.find(fn enrollment -> enrollment.user_id == user_id end)
enrollments
|> Enum.find(fn enrollment -> enrollment.course_id == course.uuid end)
) do
false ->
conn
Expand Down
3 changes: 2 additions & 1 deletion apps/web/lib/web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ defmodule Web.Router do
end

resources "/courses", Courses.CoursesController, only: [:create, :update, :index, :show] do
resources "/topics", Topics.TopicsController, only: [:create, :update, :delete] do
resources "/topics", Topics.TopicsController, only: [:create] do
resources "/activities", Activities.ActivitiesController, only: [:create]
end

resources "/enrollments", Enrollments.EnrollmentsController, only: [:index]
end

resources "/topics", Topics.TopicsController, only: [:update, :delete]
resources "/enrollments", Enrollments.EnrollmentsController, only: [:index, :create, :delete]

get "/profile", Users.ProfileController, :show
Expand Down
2 changes: 1 addition & 1 deletion apps/web/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule Web.MixProject do
deps: deps(),
test_coverage: [
summary: [
threshold: 70
threshold: 80
]
]
]
Expand Down
232 changes: 232 additions & 0 deletions apps/web/test/web/controllers/topics_controller_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
defmodule Web.TopicsControllerTest do
use ExUnit.Case
use Core.DataCase
use Web.ConnCase

import Web.Auth.Guardian
import Core.Factory

alias GoEscuelaLms.Core.Schema.Topic

setup do
course = insert!(:course)
student = insert!(:user, role: :student)
instructor = insert!(:user, role: :instructor)
organizer = insert!(:user, role: :organizer)

{:ok, student: student, instructor: instructor, organizer: organizer, course: course}
end

describe "create/2" do
test "unauthorized", %{student: student, course: course} do
{:ok, token, _} = encode_and_sign(student, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, student.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> post(~p"/api/courses/#{course.uuid}/topics", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "invalid course", %{organizer: organizer} do
{:ok, token, _} = encode_and_sign(organizer, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, organizer.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> post(~p"/api/courses/#{Faker.UUID.v4()}/topics", %{})

assert json_response(conn, 422)["errors"] == %{"detail" => "course is invalid"}
end

test "invalid enrollment", %{instructor: instructor, course: course} do
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> post(~p"/api/courses/#{course.uuid}/topics", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "invalid params", %{instructor: instructor, course: course} do
insert!(:enrollment, course_id: course.uuid, user_id: instructor.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> post(~p"/api/courses/#{course.uuid}/topics", %{name: nil})

assert json_response(conn, 422)["errors"] == %{"detail" => %{"name" => ["is required"]}}
end

test "valid params", %{instructor: instructor, course: course} do
insert!(:enrollment, course_id: course.uuid, user_id: instructor.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

name = Faker.Lorem.word()

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> post(~p"/api/courses/#{course.uuid}/topics", %{name: name})

response = json_response(conn, 200)["data"]

assert response["name"] == name
assert is_nil(response["id"]) == false
end
end

describe "update/2" do
test "unauthorized", %{student: student, course: course} do
topic = insert!(:topic, course_id: course.uuid)

{:ok, token, _} = encode_and_sign(student, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, student.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> put(~p"/api/topics/#{topic.uuid}", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "invalid topic", %{organizer: organizer} do
{:ok, token, _} = encode_and_sign(organizer, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, organizer.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> put(~p"/api/topics/#{Faker.UUID.v4()}", %{})

assert json_response(conn, 422)["errors"] == %{"detail" => "topic is invalid"}
end

test "invalid enrollment", %{instructor: instructor, course: course} do
topic = insert!(:topic, course_id: course.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> put(~p"/api/topics/#{topic.uuid}", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "invalid params", %{instructor: instructor, course: course} do
topic = insert!(:topic, course_id: course.uuid)
insert!(:enrollment, course_id: course.uuid, user_id: instructor.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> put(~p"/api/topics/#{topic.uuid}", %{name: nil})

assert json_response(conn, 422)["errors"] == %{"detail" => %{"name" => ["is required"]}}
end

test "valid params", %{instructor: instructor, course: course} do
topic = insert!(:topic, course_id: course.uuid)
insert!(:enrollment, course_id: course.uuid, user_id: instructor.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

name = Faker.Lorem.word()

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> put(~p"/api/topics/#{topic.uuid}", %{name: name})

response = json_response(conn, 200)["data"]

assert response["name"] == name
assert is_nil(response["id"]) == false
end
end

describe "delete/2" do
test "unauthorized", %{student: student, course: course} do
topic = insert!(:topic, course_id: course.uuid)

{:ok, token, _} = encode_and_sign(student, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, student.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> delete(~p"/api/topics/#{topic.uuid}", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "invalid topic", %{organizer: organizer} do
{:ok, token, _} = encode_and_sign(organizer, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, organizer.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> delete(~p"/api/topics/#{Faker.UUID.v4()}", %{})

assert json_response(conn, 422)["errors"] == %{"detail" => "topic is invalid"}
end

test "invalid enrollment", %{instructor: instructor, course: course} do
topic = insert!(:topic, course_id: course.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> delete(~p"/api/topics/#{topic.uuid}", %{})

assert json_response(conn, 403)["errors"] == %{"detail" => "Forbidden resource"}
end

test "valid delete", %{instructor: instructor, course: course} do
topic = insert!(:topic, course_id: course.uuid)
insert!(:enrollment, course_id: course.uuid, user_id: instructor.uuid)
{:ok, token, _} = encode_and_sign(instructor, %{}, token_type: :access)

conn =
session_conn()
|> put_session(:user_id, instructor.uuid)
|> put_req_header("accept", "application/json")
|> put_req_header("authorization", "Bearer " <> token)
|> delete(~p"/api/topics/#{topic.uuid}")

assert json_response(conn, 200)
assert Topic.find(topic.uuid) == nil
end
end
end
Loading
Loading