From cca97b6f37d567594adc13854b087de231f7589a Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 07:06:44 +0100 Subject: [PATCH 1/6] Create organistaion Create a new organisation on Gitea --- lib/gitea.ex | 17 +++++++++++++++ lib/httpoison_mock.ex | 51 +++++++++++++++++++++++++++++-------------- test/gitea_test.exs | 6 +++++ 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/lib/gitea.ex b/lib/gitea.ex index ef5509e..f5fac9b 100644 --- a/lib/gitea.ex +++ b/lib/gitea.ex @@ -47,6 +47,23 @@ defmodule Gitea do Gitea.Http.post(url, params) end + @doc """ + Create an organisation on Gitea + """ + @spec create_organisation(String.t(), list()) :: {:ok, map} | {:error, any} + def create_organisation(org_name, opts \\ []) do + url = api_base_url() <> "orgs" + + params = %{ + descriptions: opts[:description] || "org description", + full_name: opts[:full_name] || org_name, + username: org_name, + visibility: opts[:visibility] || "private" + } + + Gitea.Http.post(url, params) + end + @doc """ `remote_repo_delete/2` accepts two arguments: `org_name` and `repo_name`. It deletes the repo on the remote `Gitea` instance as defined diff --git a/lib/httpoison_mock.ex b/lib/httpoison_mock.ex index 6c41951..d055f93 100644 --- a/lib/httpoison_mock.ex +++ b/lib/httpoison_mock.ex @@ -10,6 +10,7 @@ defmodule Gitea.HTTPoisonMock do [github.com/dwyl/**gitea/issues**](https://github.com/dwyl/gitea/issues) """ require Logger + @remote_repo_create_response_body %{ clone_url: "https://gitea-server.fly.dev/myorg/replacethis.git", # created_at: "0001-01-01T00:00:00Z", @@ -56,10 +57,11 @@ defmodule Gitea.HTTPoisonMock do }) end - @raw_response {:ok, %HTTPoison.Response{ - body: "# public-repo\n\nplease don't update this. the tests read it.", - status_code: 200 - }} + @raw_response {:ok, + %HTTPoison.Response{ + body: "# public-repo\n\nplease don't update this. the tests read it.", + status_code: 200 + }} @doc """ `get/2` mocks the HTTPoison.get/2 function when parameters match test vars. @@ -67,14 +69,18 @@ defmodule Gitea.HTTPoisonMock do """ def get(url, _headers) do Logger.debug("Gitea.HTTPoisonMock.get/2 #{url}") + case String.contains?(url, "/raw/") do true -> @raw_response + false -> repo_name = Gitea.Helpers.get_repo_name_from_url(url) + response_body = make_repo_create_post_response_body(repo_name) |> Jason.encode!() + {:ok, %HTTPoison.Response{body: response_body, status_code: 200}} end end @@ -85,14 +91,25 @@ defmodule Gitea.HTTPoisonMock do """ def post(url, body, headers) do Logger.debug("Gitea.HTTPoisonMock.post/3 #{url}") - if String.contains?(url, "markdown/raw") do - post_raw_html(url, body, headers) - else - body_map = Jason.decode!(body) |> Useful.atomize_map_keys() - response_body = - make_repo_create_post_response_body(body_map.name) - |> Jason.encode!() - {:ok, %HTTPoison.Response{body: response_body, status_code: 200}} + + cond do + url =~ "markdown/raw" -> + post_raw_html(url, body, headers) + + url =~ "/repos/" + body_map = Jason.decode!(body) |> Useful.atomize_map_keys() + + response_body = + make_repo_create_post_response_body(body_map.name) + |> Jason.encode!() + + {:ok, %HTTPoison.Response{body: response_body, status_code: 200}} + + url =~ "/orgs" -> + {:ok, %HTTPoison.Response{body: Jason.encode!(""), status_code: 200}} + + true -> + {:error, "post url not found"} end end @@ -116,9 +133,11 @@ defmodule Gitea.HTTPoisonMock do """ def delete(url) do Logger.debug("Gitea.HTTPoisonMock.delete/1 #{url}") - {:ok, %HTTPoison.Response{ - body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}), - status_code: 200 - }} + + {:ok, + %HTTPoison.Response{ + body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}), + status_code: 200 + }} end end diff --git a/test/gitea_test.exs b/test/gitea_test.exs index 7ea66c4..ccd82e1 100644 --- a/test/gitea_test.exs +++ b/test/gitea_test.exs @@ -40,6 +40,12 @@ defmodule GiteaTest do Gitea.remote_repo_delete(org_name, repo_name) end + test "create_organistaion\2 create a new organistaion" do + org_name = "new_org" + {:ok, response} = Gitea.create_organisation(org_name) + IO.inspect(response) + end + test "remote_repo_create/3 creates a new repo on the gitea server" do org_name = "myorg" repo_name = test_repo() From 0c63210086000941163b836493355b79bf5cb395 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 08:31:02 +0100 Subject: [PATCH 2/6] Fix test for mockhttp with post request Add case to mock the different type of post requests --- lib/httpoison_mock.ex | 3 ++- test/httpoison_mock_test.exs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/httpoison_mock.ex b/lib/httpoison_mock.ex index d055f93..abf81e3 100644 --- a/lib/httpoison_mock.ex +++ b/lib/httpoison_mock.ex @@ -91,12 +91,13 @@ defmodule Gitea.HTTPoisonMock do """ def post(url, body, headers) do Logger.debug("Gitea.HTTPoisonMock.post/3 #{url}") + IO.inspect(url) cond do url =~ "markdown/raw" -> post_raw_html(url, body, headers) - url =~ "/repos/" + url =~ "/repo" -> body_map = Jason.decode!(body) |> Useful.atomize_map_keys() response_body = diff --git a/test/httpoison_mock_test.exs b/test/httpoison_mock_test.exs index a4be492..2d086c9 100644 --- a/test/httpoison_mock_test.exs +++ b/test/httpoison_mock_test.exs @@ -16,9 +16,9 @@ defmodule HttPoisonMockTest do assert status == 200 end - test "Gitea.HTTPoisonMock.post any url should return status 200" do + test "Gitea.HTTPoisonMock.post /repos/org_name should return status 200" do {:ok, %HTTPoison.Response{status_code: status, body: resp_body}} = - Gitea.HTTPoisonMock.post("hi", Jason.encode!(%{name: "simon"}), "any-header") + Gitea.HTTPoisonMock.post("/repos/myorg", Jason.encode!(%{name: "simon"}), "any-header") assert status == 200 body_map = Jason.decode!(resp_body) |> Useful.atomize_map_keys() @@ -33,6 +33,7 @@ defmodule HttPoisonMockTest do test "Gitea.HTTPoisonMock.post when url is markdown/raw should return status 200" do {:ok, %HTTPoison.Response{status_code: status, body: body}} = Gitea.HTTPoisonMock.post("markdown/raw", "any", "any") + assert status == 200 assert body == Gitea.HTTPoisonMock.raw_html() end From ce47c9087bc7c1bc5e5fcb5963841d2045d252a4 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 10:49:51 +0100 Subject: [PATCH 3/6] Update http mock for delete org Add test for delete organisation --- lib/gitea.ex | 14 ++++++++++++-- lib/http.ex | 9 +++++++-- lib/httpoison_mock.ex | 23 +++++++++++++++++------ test/gitea_test.exs | 9 +++++++-- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/lib/gitea.ex b/lib/gitea.ex index f5fac9b..077d65d 100644 --- a/lib/gitea.ex +++ b/lib/gitea.ex @@ -50,8 +50,8 @@ defmodule Gitea do @doc """ Create an organisation on Gitea """ - @spec create_organisation(String.t(), list()) :: {:ok, map} | {:error, any} - def create_organisation(org_name, opts \\ []) do + @spec remote_org_create(String.t(), list()) :: {:ok, map} | {:error, any} + def remote_org_create(org_name, opts \\ []) do url = api_base_url() <> "orgs" params = %{ @@ -64,6 +64,16 @@ defmodule Gitea do Gitea.Http.post(url, params) end + @doc """ + Create an organisation on Gitea + """ + @spec remote_org_delete(String.t()) :: {:ok, map} | {:error, any} + def remote_org_delete(org_name) do + url = api_base_url() <> "orgs/#{org_name}" + + Gitea.Http.delete(url) + end + @doc """ `remote_repo_delete/2` accepts two arguments: `org_name` and `repo_name`. It deletes the repo on the remote `Gitea` instance as defined diff --git a/lib/http.ex b/lib/http.ex index 5338746..39191e6 100644 --- a/lib/http.ex +++ b/lib/http.ex @@ -40,10 +40,11 @@ defmodule Gitea.Http do """ @spec parse_body_response({atom, String.t()} | {:error, any}) :: {:ok, map} | {:error, any} def parse_body_response({:error, err}), do: {:error, err} + def parse_body_response({:ok, response = %{status_code: 204}}), do: {:ok, response} def parse_body_response({:ok, response}) do - # Logger.debug(response) # very noisy! body = Map.get(response, :body) + if body == nil || byte_size(body) == 0 do Logger.warning("GiteaHttp.parse_body_response: response body is nil!") {:error, :no_body} @@ -63,6 +64,7 @@ defmodule Gitea.Http do @spec get(String.t()) :: {:ok, map} | {:error, any} def get(url) do Logger.debug("GiteaHttp.get #{url}") + inject_poison().get(url, json_headers()) |> parse_body_response() end @@ -94,8 +96,9 @@ defmodule Gitea.Http do # Logger.debug("raw_markdown: #{raw_markdown}") headers = [ {"Accept", "text/html"}, - auth_header(), + auth_header() ] + inject_poison().post(url, raw_markdown, headers) end @@ -109,6 +112,7 @@ defmodule Gitea.Http do def post(url, params \\ %{}) do Logger.debug("GiteaHttp.post #{url}") body = Jason.encode!(params) + inject_poison().post(url, body, json_headers()) |> parse_body_response() end @@ -120,6 +124,7 @@ defmodule Gitea.Http do @spec delete(String.t()) :: {:ok, map} | {:error, any} def delete(url) do Logger.debug("GiteaHttp.delete #{url}") + inject_poison().delete(url <> "?token=#{access_token()}") |> parse_body_response() end diff --git a/lib/httpoison_mock.ex b/lib/httpoison_mock.ex index f0ffcdb..59ddc29 100644 --- a/lib/httpoison_mock.ex +++ b/lib/httpoison_mock.ex @@ -116,7 +116,7 @@ defmodule Gitea.HTTPoisonMock do {:ok, %HTTPoison.Response{body: response_body, status_code: 200}} url =~ "/orgs" -> - {:ok, %HTTPoison.Response{body: Jason.encode!(""), status_code: 200}} + {:ok, %HTTPoison.Response{body: Jason.encode!(%{username: "new_org"}), status_code: 200}} true -> {:ok, %HTTPoison.Response{body: Jason.encode!(""), status_code: 404}} @@ -143,11 +143,22 @@ defmodule Gitea.HTTPoisonMock do """ def delete(url) do Logger.debug("Gitea.HTTPoisonMock.delete/1 #{url}") + # check delete request endpooints + cond do + # match delete org + url =~ "/orgs" -> + {:ok, + %HTTPoison.Response{ + body: "", + status_code: 204 + }} - {:ok, - %HTTPoison.Response{ - body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}), - status_code: 200 - }} + true -> + {:ok, + %HTTPoison.Response{ + body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}), + status_code: 200 + }} + end end end diff --git a/test/gitea_test.exs b/test/gitea_test.exs index 30b00d8..c56abe5 100644 --- a/test/gitea_test.exs +++ b/test/gitea_test.exs @@ -40,9 +40,14 @@ defmodule GiteaTest do Gitea.remote_repo_delete(org_name, repo_name) end - test "create_organistaion\2 create a new organistaion" do + test "remote_org_create\2 create a new organistaion" do org_name = "new_org" - {:ok, response} = Gitea.create_organisation(org_name) + {:ok, response} = Gitea.remote_org_create(org_name) + + assert response.username + # delete organisation to allow test to run again + {:ok, response_delete} = Gitea.remote_org_delete(org_name) + assert response_delete.status_code == 204 end test "remote_repo_create/3 creates a new repo on the gitea server" do From fee4d1c2f0630e6a0b624d57ac0f325078aabafd Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 10:55:05 +0100 Subject: [PATCH 4/6] Update test Update test to remove unused body value --- test/httpoison_mock_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/httpoison_mock_test.exs b/test/httpoison_mock_test.exs index ef22dd1..3f940e9 100644 --- a/test/httpoison_mock_test.exs +++ b/test/httpoison_mock_test.exs @@ -39,7 +39,7 @@ defmodule HttPoisonMockTest do end test "Gitea.HTTPoisonMock.post when url is not supported should return status 404" do - {:ok, %HTTPoison.Response{status_code: status, body: body}} = + {:ok, %HTTPoison.Response{status_code: status}} = Gitea.HTTPoisonMock.post("/not-defined", "any", "any") assert status == 404 From 572c6dc7fdff25cba8b57e61dd2ee2a9a9ac850f Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 11:05:55 +0100 Subject: [PATCH 5/6] Test create org with options when creating a new org we can pass a keyword list options --- lib/gitea.ex | 6 ++++-- test/gitea_test.exs | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/gitea.ex b/lib/gitea.ex index 077d65d..8a9a00f 100644 --- a/lib/gitea.ex +++ b/lib/gitea.ex @@ -48,7 +48,9 @@ defmodule Gitea do end @doc """ - Create an organisation on Gitea + Create an organisation on Gitea. + The second argument opts is a keyword list value + and define the description, full_name and visibility """ @spec remote_org_create(String.t(), list()) :: {:ok, map} | {:error, any} def remote_org_create(org_name, opts \\ []) do @@ -65,7 +67,7 @@ defmodule Gitea do end @doc """ - Create an organisation on Gitea + Delete an organisation on Gitea. """ @spec remote_org_delete(String.t()) :: {:ok, map} | {:error, any} def remote_org_delete(org_name) do diff --git a/test/gitea_test.exs b/test/gitea_test.exs index c56abe5..1c28c21 100644 --- a/test/gitea_test.exs +++ b/test/gitea_test.exs @@ -50,6 +50,18 @@ defmodule GiteaTest do assert response_delete.status_code == 204 end + test "remote_org_create\2 create a new organistaion with options" do + org_name = "new_org2" + + {:ok, response} = + Gitea.remote_org_create(org_name, description: "org desc", visibility: "public") + + assert response.username + # delete organisation to allow test to run again + {:ok, response_delete} = Gitea.remote_org_delete(org_name) + assert response_delete.status_code == 204 + end + test "remote_repo_create/3 creates a new repo on the gitea server" do org_name = "myorg" repo_name = test_repo() From d1b0f45e25e372f14e67d328fd37c6208e05d9bb Mon Sep 17 00:00:00 2001 From: SimonLab Date: Tue, 17 May 2022 12:52:11 +0100 Subject: [PATCH 6/6] Update remote_org_create parameters Use a Map instead of keyword list for optional API parameters see: https://github.com/dwyl/gitea/pull/8#discussion_r874701284 --- lib/gitea.ex | 16 +++++++--------- lib/http.ex | 4 ++++ test/gitea_test.exs | 18 +++++++----------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/lib/gitea.ex b/lib/gitea.ex index 8a9a00f..be78463 100644 --- a/lib/gitea.ex +++ b/lib/gitea.ex @@ -52,17 +52,15 @@ defmodule Gitea do The second argument opts is a keyword list value and define the description, full_name and visibility """ - @spec remote_org_create(String.t(), list()) :: {:ok, map} | {:error, any} - def remote_org_create(org_name, opts \\ []) do + @spec remote_org_create(%{ + required(:username) => String.t(), + optional(:description) => String.t(), + optional(:full_name) => String.t(), + optional(:visibility) => String.t() + }) :: {:ok, map} | {:error, any} + def remote_org_create(params) do url = api_base_url() <> "orgs" - params = %{ - descriptions: opts[:description] || "org description", - full_name: opts[:full_name] || org_name, - username: org_name, - visibility: opts[:visibility] || "private" - } - Gitea.Http.post(url, params) end diff --git a/lib/http.ex b/lib/http.ex index 39191e6..40af4ac 100644 --- a/lib/http.ex +++ b/lib/http.ex @@ -40,6 +40,10 @@ defmodule Gitea.Http do """ @spec parse_body_response({atom, String.t()} | {:error, any}) :: {:ok, map} | {:error, any} def parse_body_response({:error, err}), do: {:error, err} + # Deleting a repository or an organisation returns an empty string for the body value + # Instead of returning {:error, :no_body) (see next parse_body_response definition) + # the function returns {:ok, response} when the status code response is 204 + # see https://github.com/dwyl/gitea/pull/8#discussion_r874618485 def parse_body_response({:ok, response = %{status_code: 204}}), do: {:ok, response} def parse_body_response({:ok, response}) do diff --git a/test/gitea_test.exs b/test/gitea_test.exs index 1c28c21..c9ecec0 100644 --- a/test/gitea_test.exs +++ b/test/gitea_test.exs @@ -42,19 +42,15 @@ defmodule GiteaTest do test "remote_org_create\2 create a new organistaion" do org_name = "new_org" - {:ok, response} = Gitea.remote_org_create(org_name) - assert response.username - # delete organisation to allow test to run again - {:ok, response_delete} = Gitea.remote_org_delete(org_name) - assert response_delete.status_code == 204 - end - - test "remote_org_create\2 create a new organistaion with options" do - org_name = "new_org2" + params = %{ + username: "new_org", + description: "org description", + full_name: "new organisation", + visibility: "public" + } - {:ok, response} = - Gitea.remote_org_create(org_name, description: "org desc", visibility: "public") + {:ok, response} = Gitea.remote_org_create(params) assert response.username # delete organisation to allow test to run again