From d02e10cc2f97cef6db2254e6fe59eac339a998f5 Mon Sep 17 00:00:00 2001 From: Oleksii Rytov Date: Wed, 15 Nov 2023 17:16:29 +0100 Subject: [PATCH 1/5] custom finch name --- .gitignore | 1 + lib/data_for_seo/client.ex | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8632d44..26c0a97 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ erl_crash.dump # Ignore package tarball (built via "mix hex.build"). data_for_seo-*.tar +.idea/ diff --git a/lib/data_for_seo/client.ex b/lib/data_for_seo/client.ex index d2b22d4..0e5ca0a 100644 --- a/lib/data_for_seo/client.ex +++ b/lib/data_for_seo/client.ex @@ -134,8 +134,9 @@ defmodule DataForSeo.Client do defp execute_request(request, opts) do timeouts = timeout_options(opts) - - Finch.request(request, ApiFinch, timeouts) + config = Config.get_tuples() |> verify_config() + finch_name = opts[:finch_name] || config[:finch_name] || ApiFinch + Finch.request(request, finch_name, timeouts) end defp timeout_options(opts) do From b2f849f205f6c588360f179ad2ebff467c7cc8cf Mon Sep 17 00:00:00 2001 From: Oleksii Rytov Date: Wed, 15 Nov 2023 18:57:49 +0100 Subject: [PATCH 2/5] add locations for country by service --- lib/data_for_seo/api/location.ex | 26 ++++ lib/data_for_seo/client.ex | 5 + test/data_for_seo/api/location_test.exs | 40 ++++++ test/support/resp_factory.ex | 157 ++++++++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 lib/data_for_seo/api/location.ex create mode 100644 test/data_for_seo/api/location_test.exs diff --git a/lib/data_for_seo/api/location.ex b/lib/data_for_seo/api/location.ex new file mode 100644 index 0000000..84abeda --- /dev/null +++ b/lib/data_for_seo/api/location.ex @@ -0,0 +1,26 @@ +defmodule DataForSeo.API.SERP.Location do + @moduledoc """ + Provides SERP Location API interfaces. + """ + + alias DataForSeo.Client + + @doc """ + Gets all locations by country for specific service: bing, google, youtube etc + ## Examples + DataForSeo.API.SERP.Locations.get_location_by_service_and_country("us") + """ + @spec get_location_by_service_and_country(String.t(), String.t(), Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_location_by_service_and_country(service, country, opts \\ []) do + Client.get("/v3/serp/#{service}/locations/#{country}") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/client.ex b/lib/data_for_seo/client.ex index 0e5ca0a..651e131 100644 --- a/lib/data_for_seo/client.ex +++ b/lib/data_for_seo/client.ex @@ -144,10 +144,15 @@ defmodule DataForSeo.Client do receive_timeout = opts[:receive_timeout] || config[:receive_timeout] |> String.to_integer() pool_timeout = opts[:pool_timeout] || config[:pool_timeout] |> String.to_integer() + receive_timeout = opts[:receive_timeout] || config[:receive_timeout] |> to_integer() + pool_timeout = opts[:pool_timeout] || config[:pool_timeout] |> to_integer() Keyword.new( pool_timeout: pool_timeout, receive_timeout: receive_timeout ) end + + defp to_integer(value) when is_binary(value), do: String.to_integer(value) + defp to_integer(value), do: value end diff --git a/test/data_for_seo/api/location_test.exs b/test/data_for_seo/api/location_test.exs new file mode 100644 index 0000000..c1d985a --- /dev/null +++ b/test/data_for_seo/api/location_test.exs @@ -0,0 +1,40 @@ +defmodule DataForSeo.Api.LocationTest do + use ExUnit.Case + + alias DataForSeo.API.SERP.Location + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read locations by country", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/serp/google/locations/lu" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_location_by_country() + ) + end) + + assert {:ok, resp} = Location.get_location_by_service_and_country("google", "lu") + + assert %{"tasks" => [%{"result"=>locations}], "tasks_count" => 1} = resp + assert Enum.any?(locations, & &1["location_type"] == "Country" and &1["location_name"] == "Luxembourg") + assert Enum.any?(locations, & &1["location_type"] == "City" and &1["location_name"] == "Kaerjeng,Luxembourg") + + end + + +end diff --git a/test/support/resp_factory.ex b/test/support/resp_factory.ex index 023f9bd..e1a6d82 100644 --- a/test/support/resp_factory.ex +++ b/test/support/resp_factory.ex @@ -327,4 +327,161 @@ defmodule RespFactory do } """ end + + def task_get_location_by_country do + """ + { + "cost": 0, + "status_code": 20000, + "status_message": "Ok.", + "tasks_count": 1, + "tasks_error": 0, + "time": "0.0629 sec.", + "version": "0.1.20230825", + "tasks": [ + { + "cost": 0, + "data": { + "api": "serp", + "function": "locations", + "se": "google" + }, + "id": "11151921-6990-0096-0000-383626e07f8a", + "path": [ + "v3", + "serp", + "google", + "locations", + "lu" + ], + "result": [ + { + "country_iso_code": "LU", + "location_code": 2442, + "location_code_parent": null, + "location_name": "Luxembourg", + "location_type": "Country" + }, + { + "country_iso_code": "LU", + "location_code": 1009944, + "location_code_parent": 2442, + "location_name": "Kaerjeng,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009948, + "location_code_parent": 2442, + "location_name": "Bissen,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009953, + "location_code_parent": 2442, + "location_name": "Kirchberg,Luxembourg", + "location_type": "Neighborhood" + }, + { + "country_iso_code": "LU", + "location_code": 1009955, + "location_code_parent": 2442, + "location_name": "Mamer,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009958, + "location_code_parent": 2442, + "location_name": "Sanem,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009960, + "location_code_parent": 2442, + "location_name": "Strassen,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009964, + "location_code_parent": 2442, + "location_name": "Wormeldange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067741, + "location_code_parent": 2442, + "location_name": "Clemency,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067742, + "location_code_parent": 2442, + "location_name": "Wiltz,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067743, + "location_code_parent": 2442, + "location_name": "Troisvierges,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067744, + "location_code_parent": 2442, + "location_name": "Munsbach,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067745, + "location_code_parent": 2442, + "location_name": "Ettelbruck,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067746, + "location_code_parent": 2442, + "location_name": "Bertrange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067747, + "location_code_parent": 2442, + "location_name": "Bettembourg,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067748, + "location_code_parent": 2442, + "location_name": "Dudelange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067749, + "location_code_parent": 2442, + "location_name": "Luxembourg,Luxembourg", + "location_type": "City" + } + ], + "result_count": 17, + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0058 sec." + } + ] + } + """ + end end From 7aec373026b80a8e735f6c4252b2404f1b986f56 Mon Sep 17 00:00:00 2001 From: Oleksii Rytov Date: Thu, 16 Nov 2023 19:33:05 +0100 Subject: [PATCH 3/5] allow empty timeouts --- lib/data_for_seo/client.ex | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/data_for_seo/client.ex b/lib/data_for_seo/client.ex index 651e131..8f61d42 100644 --- a/lib/data_for_seo/client.ex +++ b/lib/data_for_seo/client.ex @@ -141,16 +141,13 @@ defmodule DataForSeo.Client do defp timeout_options(opts) do config = Config.get_tuples() |> verify_config() - - receive_timeout = opts[:receive_timeout] || config[:receive_timeout] |> String.to_integer() - pool_timeout = opts[:pool_timeout] || config[:pool_timeout] |> String.to_integer() - receive_timeout = opts[:receive_timeout] || config[:receive_timeout] |> to_integer() - pool_timeout = opts[:pool_timeout] || config[:pool_timeout] |> to_integer() - - Keyword.new( - pool_timeout: pool_timeout, - receive_timeout: receive_timeout - ) + [:receive_timeout, :pool_timeout] + |> Enum.reduce(opts, fn key, acc -> + case opts[key] || config[key] do + nil -> acc + value -> Keyword.put(acc, key, to_integer(value)) + end + end) end defp to_integer(value) when is_binary(value), do: String.to_integer(value) From 1c8c4136de6e0ca5d90504591176026db2551a7f Mon Sep 17 00:00:00 2001 From: Oleksii Rytov Date: Sat, 25 Nov 2023 19:06:31 +0100 Subject: [PATCH 4/5] added more api for google trends and google ad --- .../api/keywords/google_ads/languages.ex | 27 ++ .../api/keywords/google_ads/locations.ex | 27 ++ .../api/keywords/google_trends/categories.ex | 27 ++ .../api/keywords/google_trends/languages.ex | 27 ++ .../api/keywords/google_trends/locations.ex | 46 +++ .../api/labs/google/categories.ex | 27 ++ lib/data_for_seo/api/location.ex | 13 +- lib/data_for_seo/client.ex | 1 + .../keywords/google_ads/languages_test.exs | 45 +++ .../keywords/google_ads/locations_test.exs | 45 +++ .../google_trends/categories_test.exs | 47 +++ .../keywords/google_trends/languages_test.exs | 45 +++ .../keywords/google_trends/locations_test.exs | 79 ++++ .../api/labs/google/categories_test.exs | 47 +++ test/data_for_seo/api/location_test.exs | 53 +-- test/support/resp_factory.ex | 345 ++++++++++++++++++ 16 files changed, 871 insertions(+), 30 deletions(-) create mode 100644 lib/data_for_seo/api/keywords/google_ads/languages.ex create mode 100644 lib/data_for_seo/api/keywords/google_ads/locations.ex create mode 100644 lib/data_for_seo/api/keywords/google_trends/categories.ex create mode 100644 lib/data_for_seo/api/keywords/google_trends/languages.ex create mode 100644 lib/data_for_seo/api/keywords/google_trends/locations.ex create mode 100644 lib/data_for_seo/api/labs/google/categories.ex create mode 100644 test/data_for_seo/api/keywords/google_ads/languages_test.exs create mode 100644 test/data_for_seo/api/keywords/google_ads/locations_test.exs create mode 100644 test/data_for_seo/api/keywords/google_trends/categories_test.exs create mode 100644 test/data_for_seo/api/keywords/google_trends/languages_test.exs create mode 100644 test/data_for_seo/api/keywords/google_trends/locations_test.exs create mode 100644 test/data_for_seo/api/labs/google/categories_test.exs diff --git a/lib/data_for_seo/api/keywords/google_ads/languages.ex b/lib/data_for_seo/api/keywords/google_ads/languages.ex new file mode 100644 index 0000000..af82d78 --- /dev/null +++ b/lib/data_for_seo/api/keywords/google_ads/languages.ex @@ -0,0 +1,27 @@ +defmodule DataForSeo.API.Keywords.GoogleAds.Languages do + @moduledoc """ + Provides API interfaces to Keyword Data API / Google Ads / Languages : + https://docs.dataforseo.com/v3/keywords_data/google_ads/languages/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all languages for google ads + ## Examples + DataForSeo.API.Keywords.GoogleAds.Languages.get_all_languages() + """ + @spec get_all_languages(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_languages(opts \\ []) do + Client.get("/v3/keywords_data/google_ads/languages") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/keywords/google_ads/locations.ex b/lib/data_for_seo/api/keywords/google_ads/locations.ex new file mode 100644 index 0000000..cf85828 --- /dev/null +++ b/lib/data_for_seo/api/keywords/google_ads/locations.ex @@ -0,0 +1,27 @@ +defmodule DataForSeo.API.Keywords.GoogleAds.Locations do + @moduledoc """ + Provides API interfaces to Keyword Data API / Google Ads / Locations : + https://docs.dataforseo.com/v3/keywords_data/google_ads/locations/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all locations for Google Ads + ## Examples + DataForSeo.API.Keywords.GoogleAds.Locations.get_all_locations() + """ + @spec get_all_locations(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_locations(opts \\ []) do + Client.get("/v3/keywords_data/google_ads/locations") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/keywords/google_trends/categories.ex b/lib/data_for_seo/api/keywords/google_trends/categories.ex new file mode 100644 index 0000000..bbe2574 --- /dev/null +++ b/lib/data_for_seo/api/keywords/google_trends/categories.ex @@ -0,0 +1,27 @@ +defmodule DataForSeo.API.Keywords.GoogleTrends.Categories do + @moduledoc """ + Provides API interfaces to Keyword Data API / Google Trends / Categories : + https://docs.dataforseo.com/v3/keywords_data/google_trends/categories/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all categories for Google Trends + ## Examples + DataForSeo.API.Keywords.GoogleTrends.Categories.get_all_categories() + """ + @spec get_all_categories(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_categories(opts \\ []) do + Client.get("/v3/keywords_data/google_trends/categories") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/keywords/google_trends/languages.ex b/lib/data_for_seo/api/keywords/google_trends/languages.ex new file mode 100644 index 0000000..4f295b6 --- /dev/null +++ b/lib/data_for_seo/api/keywords/google_trends/languages.ex @@ -0,0 +1,27 @@ +defmodule DataForSeo.API.Keywords.GoogleTrends.Languages do + @moduledoc """ + Provides API interfaces to Keyword Data API / Google Trends / Languages : + https://docs.dataforseo.com/v3/keywords_data/google_trends/languages/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all languages for google trends + ## Examples + DataForSeo.API.Keywords.GoogleTrends.Languages.get_all_languages() + """ + @spec get_all_languages(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_languages(opts \\ []) do + Client.get("/v3/keywords_data/google_trends/languages") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/keywords/google_trends/locations.ex b/lib/data_for_seo/api/keywords/google_trends/locations.ex new file mode 100644 index 0000000..3256590 --- /dev/null +++ b/lib/data_for_seo/api/keywords/google_trends/locations.ex @@ -0,0 +1,46 @@ +defmodule DataForSeo.API.Keywords.GoogleTrends.Locations do + @moduledoc """ + Provides API interfaces to Keyword Data API / Google Trends / Locations : + https://docs.dataforseo.com/v3/keywords_data/google_trends/locations/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all locations for google trends + ## Examples + DataForSeo.API.Keywords.GoogleTrends.Locations.get_all_locations() + """ + @spec get_all_locations(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_locations(opts \\ []) do + Client.get("/v3/keywords_data/google_trends/locations") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end + + @doc """ + Gets all locations for google trends + ## Examples + DataForSeo.API.Keywords.GoogleTrends.Locations.get_all_locations_by_country("ua") + """ + @spec get_all_locations_by_country(String.t(), Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_locations_by_country(country_code, opts \\ []) do + Client.get("/v3/keywords_data/google_trends/locations/#{country_code}") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/labs/google/categories.ex b/lib/data_for_seo/api/labs/google/categories.ex new file mode 100644 index 0000000..7240c3d --- /dev/null +++ b/lib/data_for_seo/api/labs/google/categories.ex @@ -0,0 +1,27 @@ +defmodule DataForSeo.API.Labs.Google.Categories do + @moduledoc """ + Provides API interfaces to Labs / Google / Categories API: + https://docs.dataforseo.com/v3/dataforseo_labs/categories_list/ + """ + + alias DataForSeo.Client + + @doc """ + Gets all locations by country for specific service: bing, google, youtube etc + ## Examples + DataForSeo.API.Labs.Google.Categories.get_all_categories() + """ + @spec get_all_categories(Keyword.t()) :: {:ok, map()} | {:error, term()} + def get_all_categories(opts \\ []) do + Client.get("/v3/dataforseo_labs/categories") + |> Client.validate_status_code() + |> Client.decode_json_response(opts) + |> case do + {:ok, resp} -> + {:ok, resp} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/data_for_seo/api/location.ex b/lib/data_for_seo/api/location.ex index 84abeda..9d6b66b 100644 --- a/lib/data_for_seo/api/location.ex +++ b/lib/data_for_seo/api/location.ex @@ -10,17 +10,18 @@ defmodule DataForSeo.API.SERP.Location do ## Examples DataForSeo.API.SERP.Locations.get_location_by_service_and_country("us") """ - @spec get_location_by_service_and_country(String.t(), String.t(), Keyword.t()) :: {:ok, map()} | {:error, term()} + @spec get_location_by_service_and_country(String.t(), String.t(), Keyword.t()) :: + {:ok, map()} | {:error, term()} def get_location_by_service_and_country(service, country, opts \\ []) do Client.get("/v3/serp/#{service}/locations/#{country}") |> Client.validate_status_code() |> Client.decode_json_response(opts) |> case do - {:ok, resp} -> - {:ok, resp} + {:ok, resp} -> + {:ok, resp} - {:error, error} -> - {:error, error} - end + {:error, error} -> + {:error, error} + end end end diff --git a/lib/data_for_seo/client.ex b/lib/data_for_seo/client.ex index 8f61d42..50b07f2 100644 --- a/lib/data_for_seo/client.ex +++ b/lib/data_for_seo/client.ex @@ -141,6 +141,7 @@ defmodule DataForSeo.Client do defp timeout_options(opts) do config = Config.get_tuples() |> verify_config() + [:receive_timeout, :pool_timeout] |> Enum.reduce(opts, fn key, acc -> case opts[key] || config[key] do diff --git a/test/data_for_seo/api/keywords/google_ads/languages_test.exs b/test/data_for_seo/api/keywords/google_ads/languages_test.exs new file mode 100644 index 0000000..48dfe80 --- /dev/null +++ b/test/data_for_seo/api/keywords/google_ads/languages_test.exs @@ -0,0 +1,45 @@ +defmodule DataForSeo.Api.Keywords.GoogleAds.LanguagesTest do + use ExUnit.Case + + alias DataForSeo.API.Keywords.GoogleAds.Languages + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read languages", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_ads/languages" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_ads_languages() + ) + end) + + assert {:ok, resp} = Languages.get_all_languages() + + assert %{"tasks" => [%{"result" => languages}], "tasks_count" => 1} = resp + + assert Enum.any?( + languages, + &(&1["language_name"] == "Bulgarian" and &1["language_code"] == "bg") + ) + + assert Enum.any?( + languages, + &(&1["language_name"] == "Croatian" and &1["language_code"] == "hr") + ) + end +end diff --git a/test/data_for_seo/api/keywords/google_ads/locations_test.exs b/test/data_for_seo/api/keywords/google_ads/locations_test.exs new file mode 100644 index 0000000..31ebce1 --- /dev/null +++ b/test/data_for_seo/api/keywords/google_ads/locations_test.exs @@ -0,0 +1,45 @@ +defmodule DataForSeo.Api.Keywords.GoogleAds.LocationsTest do + use ExUnit.Case + + alias DataForSeo.API.Keywords.GoogleAds.Locations + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read all locations", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_ads/locations" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_ads_locations() + ) + end) + + assert {:ok, resp} = Locations.get_all_locations() + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + loc = %{ + "location_code" => 21133, + "location_name" => "Alabama,United States", + "location_code_parent" => 2840, + "country_iso_code" => "US", + "location_type" => "State" + } + + assert Enum.any?(locations, &(&1 == loc)) + end +end diff --git a/test/data_for_seo/api/keywords/google_trends/categories_test.exs b/test/data_for_seo/api/keywords/google_trends/categories_test.exs new file mode 100644 index 0000000..fa87abf --- /dev/null +++ b/test/data_for_seo/api/keywords/google_trends/categories_test.exs @@ -0,0 +1,47 @@ +defmodule DataForSeo.Api.Keywords.GoogleTrends.CategoriesTest do + use ExUnit.Case + + alias DataForSeo.API.Keywords.GoogleTrends.Categories + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read categories", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_trends/categories" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_trends_categories() + ) + end) + + assert {:ok, resp} = Categories.get_all_categories() + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + assert Enum.any?( + locations, + &(&1["category_name"] == "Apparel" and &1["category_code"] == 10021 and + &1["category_code_parent"] == nil) + ) + + assert Enum.any?( + locations, + &(&1["category_name"] == "Apparel Accessories" and &1["category_code"] == 10178 and + &1["category_code_parent"] == 10021) + ) + end +end diff --git a/test/data_for_seo/api/keywords/google_trends/languages_test.exs b/test/data_for_seo/api/keywords/google_trends/languages_test.exs new file mode 100644 index 0000000..d4f4097 --- /dev/null +++ b/test/data_for_seo/api/keywords/google_trends/languages_test.exs @@ -0,0 +1,45 @@ +defmodule DataForSeo.Api.Keywords.GoogleTrends.LanguagesTest do + use ExUnit.Case + + alias DataForSeo.API.Keywords.GoogleTrends.Languages + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read languages", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_trends/languages" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_trend_languages() + ) + end) + + assert {:ok, resp} = Languages.get_all_languages() + + assert %{"tasks" => [%{"result" => languages}], "tasks_count" => 1} = resp + + assert Enum.any?( + languages, + &(&1["language_name"] == "Afrikaans" and &1["language_code"] == "af") + ) + + assert Enum.any?( + languages, + &(&1["language_name"] == "German" and &1["language_code"] == "de") + ) + end +end diff --git a/test/data_for_seo/api/keywords/google_trends/locations_test.exs b/test/data_for_seo/api/keywords/google_trends/locations_test.exs new file mode 100644 index 0000000..5133b08 --- /dev/null +++ b/test/data_for_seo/api/keywords/google_trends/locations_test.exs @@ -0,0 +1,79 @@ +defmodule DataForSeo.Api.Keywords.GoogleTrends.LocationsTest do + use ExUnit.Case + + alias DataForSeo.API.Keywords.GoogleTrends.Locations + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read all locations", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_trends/locations" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_trend_locations() + ) + end) + + assert {:ok, resp} = Locations.get_all_locations() + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + loc = %{ + "location_code" => 2004, + "location_name" => "Afghanistan", + "location_code_parent" => nil, + "country_iso_code" => "AF", + "location_type" => "Country", + "geo_name" => "Afghanistan", + "geo_id" => "AF" + } + + assert Enum.any?(locations, &(&1 == loc)) + end + + test "read locations by country", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/keywords_data/google_trends/locations/ua" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_trend_locations_by_country("ua") + ) + end) + + assert {:ok, resp} = Locations.get_all_locations_by_country("ua") + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + loc = %{ + "location_code" => 21113, + "location_name" => "Donetsk Oblast,Ukraine", + "location_code_parent" => 2804, + "country_iso_code" => "UA", + "location_type" => "Region", + "geo_name" => "Donetsk Oblast,Ukraine", + "geo_id" => "Donetsk Oblast,Ukraine" + } + + assert Enum.any?(locations, &(&1 == loc)) + end +end diff --git a/test/data_for_seo/api/labs/google/categories_test.exs b/test/data_for_seo/api/labs/google/categories_test.exs new file mode 100644 index 0000000..44d40b3 --- /dev/null +++ b/test/data_for_seo/api/labs/google/categories_test.exs @@ -0,0 +1,47 @@ +defmodule DataForSeo.Api.Labs.Google.CategoriesTest do + use ExUnit.Case + + alias DataForSeo.API.Labs.Google.Categories + + import RespFactory + + setup do + bypass = Bypass.open() + + DataForSeo.Config.add(:process, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "read categories", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/dataforseo_labs/categories" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_google_categories() + ) + end) + + assert {:ok, resp} = Categories.get_all_categories() + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + assert Enum.any?( + locations, + &(&1["category_name"] == "Apparel" and &1["category_code"] == 10021 and + &1["category_code_parent"] == nil) + ) + + assert Enum.any?( + locations, + &(&1["category_name"] == "Apparel Accessories" and &1["category_code"] == 10178 and + &1["category_code_parent"] == 10021) + ) + end +end diff --git a/test/data_for_seo/api/location_test.exs b/test/data_for_seo/api/location_test.exs index c1d985a..b9eeccf 100644 --- a/test/data_for_seo/api/location_test.exs +++ b/test/data_for_seo/api/location_test.exs @@ -13,28 +13,33 @@ defmodule DataForSeo.Api.LocationTest do {:ok, bypass: bypass} end - test "read locations by country", %{bypass: bypass} do - Bypass.expect(bypass, fn conn -> - assert "GET" = conn.method - assert "/v3/serp/google/locations/lu" = conn.request_path - assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) - - assert {:ok, "", _} = Plug.Conn.read_body(conn) - - Plug.Conn.resp( - conn, - 200, - task_get_location_by_country() - ) - end) - - assert {:ok, resp} = Location.get_location_by_service_and_country("google", "lu") - - assert %{"tasks" => [%{"result"=>locations}], "tasks_count" => 1} = resp - assert Enum.any?(locations, & &1["location_type"] == "Country" and &1["location_name"] == "Luxembourg") - assert Enum.any?(locations, & &1["location_type"] == "City" and &1["location_name"] == "Kaerjeng,Luxembourg") - - end - - + test "read locations by country", %{bypass: bypass} do + Bypass.expect(bypass, fn conn -> + assert "GET" = conn.method + assert "/v3/serp/google/locations/lu" = conn.request_path + assert Enum.member?(conn.req_headers, {"content-type", "application/json"}) + + assert {:ok, "", _} = Plug.Conn.read_body(conn) + + Plug.Conn.resp( + conn, + 200, + task_get_location_by_country() + ) + end) + + assert {:ok, resp} = Location.get_location_by_service_and_country("google", "lu") + + assert %{"tasks" => [%{"result" => locations}], "tasks_count" => 1} = resp + + assert Enum.any?( + locations, + &(&1["location_type"] == "Country" and &1["location_name"] == "Luxembourg") + ) + + assert Enum.any?( + locations, + &(&1["location_type"] == "City" and &1["location_name"] == "Kaerjeng,Luxembourg") + ) + end end diff --git a/test/support/resp_factory.ex b/test/support/resp_factory.ex index e1a6d82..6c2b3c4 100644 --- a/test/support/resp_factory.ex +++ b/test/support/resp_factory.ex @@ -484,4 +484,349 @@ defmodule RespFactory do } """ end + + def task_get_google_categories do + """ + { + "version": "0.1.20200305", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0594 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "03061224-1535-0197-0000-4d85996ce1db", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0015 sec.", + "cost": 0, + "result_count": 3180, + "path": [ + "v3", + "dataforseo_labs", + "categories" + ], + "data": { + "api": "dataforseo_labs", + "function": "categories" + }, + "result": [ + { + "category_code": 10021, + "category_name": "Apparel", + "category_code_parent": null + }, + { + "category_code": 10178, + "category_name": "Apparel Accessories", + "category_code_parent": 10021 + }, + { + "category_code": 10937, + "category_name": "Bags & Packs", + "category_code_parent": 10178 + }, + { + "category_code": 12262, + "category_name": "Backpacks & Utility Bags", + "category_code_parent": 10937 + } + ] + } + ] + } + """ + end + + def task_get_google_trends_categories do + task_get_google_categories() + end + + def task_get_google_trend_languages do + """ + { + "version": "0.1.20200408", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1977 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "04081302-1535-0119-0000-cf474e770569", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0002 sec.", + "cost": 0, + "result_count": 231, + "path": [ + "v3", + "keywords_data", + "google_trends", + "languages" + ], + "data": { + "api": "keywords_data", + "function": "languages", + "se": "google_trends" + }, + "result": [ + { + "language_name": "Afrikaans", + "language_code": "af" + }, + { + "language_name": "Albanian", + "language_code": "sq" + }, + { + "language_name": "English", + "language_code": "en" + }, + { + "language_name": "German", + "language_code": "de" + } + ] + } + ] + } + """ + end + + def task_get_google_trend_locations do + """ + { + "version": "0.1.20210917", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1012 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "09201832-1535-0120-0000-012e5cc7e0d9", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0244 sec.", + "cost": 0, + "result_count": 2383, + "path": [ + "v3", + "keywords_data", + "google_trends", + "locations" + ], + "data": { + "api": "keywords_data", + "function": "locations", + "se": "google_trends" + }, + "result": [ + { + "location_code": 2004, + "location_name": "Afghanistan", + "location_code_parent": null, + "country_iso_code": "AF", + "location_type": "Country", + "geo_name": "Afghanistan", + "geo_id": "AF" + }, + { + "location_code": 2008, + "location_name": "Albania", + "location_code_parent": null, + "country_iso_code": "AL", + "location_type": "Country", + "geo_name": "Albania", + "geo_id": "AL" + }, + { + "location_code": 2010, + "location_name": "Antarctica", + "location_code_parent": null, + "country_iso_code": "AQ", + "location_type": "Country", + "geo_name": "Antarctica", + "geo_id": "AQ" + }, + { + "location_code": 2012, + "location_name": "Algeria", + "location_code_parent": null, + "country_iso_code": "DZ", + "location_type": "Country", + "geo_name": "Algeria", + "geo_id": "DZ" + }, + { + "location_code": 2016, + "location_name": "American Samoa", + "location_code_parent": null, + "country_iso_code": "AS", + "location_type": "Country", + "geo_name": "American Samoa", + "geo_id": "AS" + }, + { + "location_code": 2020, + "location_name": "Andorra", + "location_code_parent": null, + "country_iso_code": "AD", + "location_type": "Country", + "geo_name": "Andorra", + "geo_id": "AD" + }, + { + "location_code": 2024, + "location_name": "Angola", + "location_code_parent": null, + "country_iso_code": "AO", + "location_type": "Country", + "geo_name": "Angola", + "geo_id": "AO" + }, + { + "location_code": 21113, + "location_name": "Donetsk Oblast,Ukraine", + "location_code_parent": 2804, + "country_iso_code": "UA", + "location_type": "Region", + "geo_name": "Donetsk Oblast,Ukraine", + "geo_id": "Donetsk Oblast,Ukraine" + } + ] + } + ] + } + """ + end + + def task_get_google_trend_locations_by_country(_) do + # same fixture at the moment b/c there are no difference with all locations list + # only testing a success routing to the url and response format + task_get_google_trend_locations() + end + + def task_get_google_ads_locations do + """ + { + "version": "3.20191128", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.4305 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11061103-0696-0120-0000-268044305ce6", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.2547 sec.", + "cost": 0, + "result_count": 94933, + "path": [ + "v3", + "keywords_data", + "google_ads", + "locations" + ], + "data": { + "api": "keywords_data", + "function": "locations", + "se": "google_ads" + }, + "result": [ + { + "location_code": 2840, + "location_name": "United States", + "location_code_parent": null, + "country_iso_code": "US", + "location_type": "Country" + }, + { + "location_code": 21132, + "location_name": "Alaska,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + }, + { + "location_code": 21133, + "location_name": "Alabama,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + }, + { + "location_code": 21135, + "location_name": "Arkansas,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + } + ] + } + ] + } + """ + end + + def task_get_google_ads_languages do + """ + { + "version": "3.20191128", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1773 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11061103-0696-0119-0000-a74d6a2ce740", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0000 sec.", + "cost": 0, + "result_count": 43, + "path": [ + "v3", + "keywords_data", + "google_ads", + "languages" + ], + "data": { + "api": "keywords_data", + "function": "languages", + "se": "google_ads" + }, + "result": [ + { + "language_name": "Arabic", + "language_code": "ar" + }, + { + "language_name": "Bulgarian", + "language_code": "bg" + }, + { + "language_name": "Catalan", + "language_code": "ca" + }, + { + "language_name": "Croatian", + "language_code": "hr" + } + ] + } + ] + } + """ + end end From c8e2c1cc52b59f1a88c9bf21c084eff9023d6c7c Mon Sep 17 00:00:00 2001 From: Oleksii Rytov Date: Sat, 25 Nov 2023 19:34:09 +0100 Subject: [PATCH 5/5] moved fixtures into json files under proper API tree --- .../api/{ => serp/google}/location.ex | 6 +- lib/data_for_seo/api/serp/google/organic.ex | 10 + .../keywords/google_ads/languages.json | 48 + .../keywords/google_ads/locations.json | 60 ++ .../keywords/google_trends/categories.json | 50 ++ .../keywords/google_trends/languages.json | 48 + .../keywords/google_trends/locations.json | 104 +++ priv/fixtures/labs/google/categories.json | 50 ++ priv/fixtures/serp/google/locations-lu.json | 152 ++++ .../serp/google/organic/task-get.json | 151 ++++ .../serp/google/organic/task-post-single.json | 38 + .../serp/google/organic/task-post.json | 68 ++ .../serp/google/organic/tasks-ready.json | 52 ++ .../keywords/google_trends/languages_test.exs | 2 +- .../api/labs/google/categories_test.exs | 2 +- .../api/{ => serp/google}/location_test.exs | 6 +- test/support/resp_factory.ex | 825 +----------------- 17 files changed, 868 insertions(+), 804 deletions(-) rename lib/data_for_seo/api/{ => serp/google}/location.ex (77%) create mode 100644 lib/data_for_seo/api/serp/google/organic.ex create mode 100644 priv/fixtures/keywords/google_ads/languages.json create mode 100644 priv/fixtures/keywords/google_ads/locations.json create mode 100644 priv/fixtures/keywords/google_trends/categories.json create mode 100644 priv/fixtures/keywords/google_trends/languages.json create mode 100644 priv/fixtures/keywords/google_trends/locations.json create mode 100644 priv/fixtures/labs/google/categories.json create mode 100644 priv/fixtures/serp/google/locations-lu.json create mode 100644 priv/fixtures/serp/google/organic/task-get.json create mode 100644 priv/fixtures/serp/google/organic/task-post-single.json create mode 100644 priv/fixtures/serp/google/organic/task-post.json create mode 100644 priv/fixtures/serp/google/organic/tasks-ready.json rename test/data_for_seo/api/{ => serp/google}/location_test.exs (88%) diff --git a/lib/data_for_seo/api/location.ex b/lib/data_for_seo/api/serp/google/location.ex similarity index 77% rename from lib/data_for_seo/api/location.ex rename to lib/data_for_seo/api/serp/google/location.ex index 9d6b66b..a7c5bc1 100644 --- a/lib/data_for_seo/api/location.ex +++ b/lib/data_for_seo/api/serp/google/location.ex @@ -1,6 +1,6 @@ -defmodule DataForSeo.API.SERP.Location do +defmodule DataForSeo.API.SERP.Google.Location do @moduledoc """ - Provides SERP Location API interfaces. + Provides SERP Google Location API interfaces. """ alias DataForSeo.Client @@ -8,7 +8,7 @@ defmodule DataForSeo.API.SERP.Location do @doc """ Gets all locations by country for specific service: bing, google, youtube etc ## Examples - DataForSeo.API.SERP.Locations.get_location_by_service_and_country("us") + DataForSeo.API.SERP.Google.Locations.get_location_by_service_and_country("us") """ @spec get_location_by_service_and_country(String.t(), String.t(), Keyword.t()) :: {:ok, map()} | {:error, term()} diff --git a/lib/data_for_seo/api/serp/google/organic.ex b/lib/data_for_seo/api/serp/google/organic.ex new file mode 100644 index 0000000..89d0a1e --- /dev/null +++ b/lib/data_for_seo/api/serp/google/organic.ex @@ -0,0 +1,10 @@ +defmodule DataForSeo.API.SERP.Google.Organic do + @moduledoc """ + Provides SERP Google API interfaces to organic search results + It's a wrapper b/c original lib had no namespaces and implementation is at `DataForSeo.API.Serp` + At the moment it's only import existing module but here is a room to improvements and keeping back compatibilities + at the same time. + """ + + import DataForSeo.API.Serp +end diff --git a/priv/fixtures/keywords/google_ads/languages.json b/priv/fixtures/keywords/google_ads/languages.json new file mode 100644 index 0000000..3bd484a --- /dev/null +++ b/priv/fixtures/keywords/google_ads/languages.json @@ -0,0 +1,48 @@ +{ + "version": "3.20191128", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1773 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11061103-0696-0119-0000-a74d6a2ce740", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0000 sec.", + "cost": 0, + "result_count": 43, + "path": [ + "v3", + "keywords_data", + "google_ads", + "languages" + ], + "data": { + "api": "keywords_data", + "function": "languages", + "se": "google_ads" + }, + "result": [ + { + "language_name": "Arabic", + "language_code": "ar" + }, + { + "language_name": "Bulgarian", + "language_code": "bg" + }, + { + "language_name": "Catalan", + "language_code": "ca" + }, + { + "language_name": "Croatian", + "language_code": "hr" + } + ] + } + ] +} diff --git a/priv/fixtures/keywords/google_ads/locations.json b/priv/fixtures/keywords/google_ads/locations.json new file mode 100644 index 0000000..2d4b5a5 --- /dev/null +++ b/priv/fixtures/keywords/google_ads/locations.json @@ -0,0 +1,60 @@ +{ + "version": "3.20191128", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.4305 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11061103-0696-0120-0000-268044305ce6", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.2547 sec.", + "cost": 0, + "result_count": 94933, + "path": [ + "v3", + "keywords_data", + "google_ads", + "locations" + ], + "data": { + "api": "keywords_data", + "function": "locations", + "se": "google_ads" + }, + "result": [ + { + "location_code": 2840, + "location_name": "United States", + "location_code_parent": null, + "country_iso_code": "US", + "location_type": "Country" + }, + { + "location_code": 21132, + "location_name": "Alaska,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + }, + { + "location_code": 21133, + "location_name": "Alabama,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + }, + { + "location_code": 21135, + "location_name": "Arkansas,United States", + "location_code_parent": 2840, + "country_iso_code": "US", + "location_type": "State" + } + ] + } + ] +} diff --git a/priv/fixtures/keywords/google_trends/categories.json b/priv/fixtures/keywords/google_trends/categories.json new file mode 100644 index 0000000..ad183ac --- /dev/null +++ b/priv/fixtures/keywords/google_trends/categories.json @@ -0,0 +1,50 @@ +{ + "version": "0.1.20200305", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0594 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "03061224-1535-0197-0000-4d85996ce1db", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0015 sec.", + "cost": 0, + "result_count": 3180, + "path": [ + "v3", + "dataforseo_labs", + "categories" + ], + "data": { + "api": "dataforseo_labs", + "function": "categories" + }, + "result": [ + { + "category_code": 10021, + "category_name": "Apparel", + "category_code_parent": null + }, + { + "category_code": 10178, + "category_name": "Apparel Accessories", + "category_code_parent": 10021 + }, + { + "category_code": 10937, + "category_name": "Bags & Packs", + "category_code_parent": 10178 + }, + { + "category_code": 12262, + "category_name": "Backpacks & Utility Bags", + "category_code_parent": 10937 + } + ] + } + ] +} diff --git a/priv/fixtures/keywords/google_trends/languages.json b/priv/fixtures/keywords/google_trends/languages.json new file mode 100644 index 0000000..6da448c --- /dev/null +++ b/priv/fixtures/keywords/google_trends/languages.json @@ -0,0 +1,48 @@ +{ + "version": "0.1.20200408", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1977 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "04081302-1535-0119-0000-cf474e770569", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0002 sec.", + "cost": 0, + "result_count": 231, + "path": [ + "v3", + "keywords_data", + "google_trends", + "languages" + ], + "data": { + "api": "keywords_data", + "function": "languages", + "se": "google_trends" + }, + "result": [ + { + "language_name": "Afrikaans", + "language_code": "af" + }, + { + "language_name": "Albanian", + "language_code": "sq" + }, + { + "language_name": "English", + "language_code": "en" + }, + { + "language_name": "German", + "language_code": "de" + } + ] + } + ] +} diff --git a/priv/fixtures/keywords/google_trends/locations.json b/priv/fixtures/keywords/google_trends/locations.json new file mode 100644 index 0000000..30af7a1 --- /dev/null +++ b/priv/fixtures/keywords/google_trends/locations.json @@ -0,0 +1,104 @@ +{ + "version": "0.1.20210917", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.1012 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "09201832-1535-0120-0000-012e5cc7e0d9", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0244 sec.", + "cost": 0, + "result_count": 2383, + "path": [ + "v3", + "keywords_data", + "google_trends", + "locations" + ], + "data": { + "api": "keywords_data", + "function": "locations", + "se": "google_trends" + }, + "result": [ + { + "location_code": 2004, + "location_name": "Afghanistan", + "location_code_parent": null, + "country_iso_code": "AF", + "location_type": "Country", + "geo_name": "Afghanistan", + "geo_id": "AF" + }, + { + "location_code": 2008, + "location_name": "Albania", + "location_code_parent": null, + "country_iso_code": "AL", + "location_type": "Country", + "geo_name": "Albania", + "geo_id": "AL" + }, + { + "location_code": 2010, + "location_name": "Antarctica", + "location_code_parent": null, + "country_iso_code": "AQ", + "location_type": "Country", + "geo_name": "Antarctica", + "geo_id": "AQ" + }, + { + "location_code": 2012, + "location_name": "Algeria", + "location_code_parent": null, + "country_iso_code": "DZ", + "location_type": "Country", + "geo_name": "Algeria", + "geo_id": "DZ" + }, + { + "location_code": 2016, + "location_name": "American Samoa", + "location_code_parent": null, + "country_iso_code": "AS", + "location_type": "Country", + "geo_name": "American Samoa", + "geo_id": "AS" + }, + { + "location_code": 2020, + "location_name": "Andorra", + "location_code_parent": null, + "country_iso_code": "AD", + "location_type": "Country", + "geo_name": "Andorra", + "geo_id": "AD" + }, + { + "location_code": 2024, + "location_name": "Angola", + "location_code_parent": null, + "country_iso_code": "AO", + "location_type": "Country", + "geo_name": "Angola", + "geo_id": "AO" + }, + { + "location_code": 21113, + "location_name": "Donetsk Oblast,Ukraine", + "location_code_parent": 2804, + "country_iso_code": "UA", + "location_type": "Region", + "geo_name": "Donetsk Oblast,Ukraine", + "geo_id": "Donetsk Oblast,Ukraine" + } + ] + } + ] +} diff --git a/priv/fixtures/labs/google/categories.json b/priv/fixtures/labs/google/categories.json new file mode 100644 index 0000000..ad183ac --- /dev/null +++ b/priv/fixtures/labs/google/categories.json @@ -0,0 +1,50 @@ +{ + "version": "0.1.20200305", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0594 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "03061224-1535-0197-0000-4d85996ce1db", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0015 sec.", + "cost": 0, + "result_count": 3180, + "path": [ + "v3", + "dataforseo_labs", + "categories" + ], + "data": { + "api": "dataforseo_labs", + "function": "categories" + }, + "result": [ + { + "category_code": 10021, + "category_name": "Apparel", + "category_code_parent": null + }, + { + "category_code": 10178, + "category_name": "Apparel Accessories", + "category_code_parent": 10021 + }, + { + "category_code": 10937, + "category_name": "Bags & Packs", + "category_code_parent": 10178 + }, + { + "category_code": 12262, + "category_name": "Backpacks & Utility Bags", + "category_code_parent": 10937 + } + ] + } + ] +} diff --git a/priv/fixtures/serp/google/locations-lu.json b/priv/fixtures/serp/google/locations-lu.json new file mode 100644 index 0000000..4a57e35 --- /dev/null +++ b/priv/fixtures/serp/google/locations-lu.json @@ -0,0 +1,152 @@ +{ + "cost": 0, + "status_code": 20000, + "status_message": "Ok.", + "tasks_count": 1, + "tasks_error": 0, + "time": "0.0629 sec.", + "version": "0.1.20230825", + "tasks": [ + { + "cost": 0, + "data": { + "api": "serp", + "function": "locations", + "se": "google" + }, + "id": "11151921-6990-0096-0000-383626e07f8a", + "path": [ + "v3", + "serp", + "google", + "locations", + "lu" + ], + "result": [ + { + "country_iso_code": "LU", + "location_code": 2442, + "location_code_parent": null, + "location_name": "Luxembourg", + "location_type": "Country" + }, + { + "country_iso_code": "LU", + "location_code": 1009944, + "location_code_parent": 2442, + "location_name": "Kaerjeng,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009948, + "location_code_parent": 2442, + "location_name": "Bissen,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009953, + "location_code_parent": 2442, + "location_name": "Kirchberg,Luxembourg", + "location_type": "Neighborhood" + }, + { + "country_iso_code": "LU", + "location_code": 1009955, + "location_code_parent": 2442, + "location_name": "Mamer,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009958, + "location_code_parent": 2442, + "location_name": "Sanem,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009960, + "location_code_parent": 2442, + "location_name": "Strassen,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 1009964, + "location_code_parent": 2442, + "location_name": "Wormeldange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067741, + "location_code_parent": 2442, + "location_name": "Clemency,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067742, + "location_code_parent": 2442, + "location_name": "Wiltz,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067743, + "location_code_parent": 2442, + "location_name": "Troisvierges,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067744, + "location_code_parent": 2442, + "location_name": "Munsbach,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067745, + "location_code_parent": 2442, + "location_name": "Ettelbruck,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067746, + "location_code_parent": 2442, + "location_name": "Bertrange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067747, + "location_code_parent": 2442, + "location_name": "Bettembourg,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067748, + "location_code_parent": 2442, + "location_name": "Dudelange,Luxembourg", + "location_type": "City" + }, + { + "country_iso_code": "LU", + "location_code": 9067749, + "location_code_parent": 2442, + "location_name": "Luxembourg,Luxembourg", + "location_type": "City" + } + ], + "result_count": 17, + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0058 sec." + } + ] +} diff --git a/priv/fixtures/serp/google/organic/task-get.json b/priv/fixtures/serp/google/organic/task-get.json new file mode 100644 index 0000000..6afacc6 --- /dev/null +++ b/priv/fixtures/serp/google/organic/task-get.json @@ -0,0 +1,151 @@ +{ + "version": "0.1.20200129", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.3059 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11151456-0696-0066-0000-002a5915da37", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0952 sec.", + "cost": 0, + "result_count": 1, + "path": [ + "v3", + "serp", + "google", + "organic", + "task_get", + "regular", + "11151456-0696-0066-0000-002a5915da37" + ], + "data": { + "api": "serp", + "function": "task_get", + "se": "google", + "se_type": "organic", + "language_name": "English", + "location_name": "United States", + "keyword": "flight ticket new york san francisco", + "priority": "2", + "tag": "tag2", + "device": "desktop", + "os": "windows" + }, + "result": [ + { + "keyword": "flight ticket new york san francisco", + "type": "organic", + "se_domain": "google.com", + "location_code": 2840, + "language_code": "en", + "check_url": "https://www.google.com/search?q=flight%20ticket%20new%20york%20san%20francisco&num=100&hl=en&gl=US&gws_rd=cr&ie=UTF-8&oe=UTF-8&uule=w+CAIQIFISCQs2MuSEtepUEUK33kOSuTsc", + "datetime": "2019-11-15 12:57:46 +00:00", + "spell": null, + "item_types": [ + "organic", + "paid" + ], + "se_results_count": 85600000, + "items_count": 96, + "items": [ + { + "type": "paid", + "rank_group": 1, + "rank_absolute": 1, + "domain": "www.bookingbuddy.com", + "title": "Flights To Lwo | Unbelievably Cheap Flights | BookingBuddy.com‎", + "description": "Compare Airlines & Sites. Cheap Flights on BookingBuddy, a TripAdvisor Company", + "url": "https://www.bookingbuddy.com/en/hero/", + "breadcrumb": "www.bookingbuddy.com/Flights" + }, + { + "type": "paid", + "rank_group": 2, + "rank_absolute": 2, + "domain": "www.trip.com", + "title": "Cheap Flight Tickets | Search & Find Deals on Flights | trip.com‎", + "description": "Wide Selection of Cheap Flights Online. Explore & Save with Trip.com! Fast, Easy & Secure...", + "url": "https://www.trip.com/flights/index?utm_campaign=GG_SE_All_en_Flight_Generic_NA_Phrase", + "breadcrumb": "www.trip.com/" + }, + { + "type": "paid", + "rank_group": 3, + "rank_absolute": 4, + "domain": "www.kayak.com", + "title": "Find the Cheapest Flights | Search, Compare & Save Today‎", + "description": "Cheap Flights, Airline Tickets and Flight Deals. Compare 100s of Airlines Worldwide. Search...", + "url": "https://www.kayak.com/horizon/sem/flights/general", + "breadcrumb": "www.kayak.com/flights" + }, + { + "type": "organic", + "rank_group": 1, + "rank_absolute": 5, + "domain": "www.kayak.com", + "title": "Cheap Flights from New York to San Francisco from $182 ...", + "description": "Fly from New York to San Francisco on Frontier from $182, United Airlines from ... the cheapest round-trip tickets were found on Frontier ($182), United Airlines ...", + "url": "https://www.kayak.com/flight-routes/New-York-NYC/San-Francisco-SFO", + "breadcrumb": "https://www.kayak.com › Flights › North America › United States › California" + }, + { + "type": "organic", + "rank_group": 2, + "rank_absolute": 6, + "domain": "www.skyscanner.com", + "title": "Cheap flights from New York to San Francisco SFO from $123 ...", + "description": "Flight information New York to San Francisco International .... tool will help you find the cheapest tickets from New York in San Francisco in just a few clicks.", + "url": "https://www.skyscanner.com/routes/nyca/sfo/new-york-to-san-francisco-international.html", + "breadcrumb": "https://www.skyscanner.com › United States › New York" + }, + { + "type": "organic", + "rank_group": 3, + "rank_absolute": 7, + "domain": "www.expedia.com", + "title": "JFK to SFO: Flights from New York to San Francisco for 2019 ...", + "description": "Book your New York (JFK) to San Francisco (SFO) flight with our Best Price ... How much is a plane ticket to San Francisco (SFO) from New York (JFK)?.", + "url": "https://www.expedia.com/lp/flights/jfk/sfo/new-york-to-san-francisco", + "breadcrumb": "https://www.expedia.com › flights › jfk › sfo › new-york-to-san-francisco" + }, + { + "type": "organic", + "rank_group": 94, + "rank_absolute": 97, + "domain": "www.ethiopianairlines.com", + "title": "Ethiopian Airlines | Book your next flight online and Fly Ethiopian", + "description": "Fly to your Favorite International Destination with Ethiopian Airlines. Book your Flights Online for Best Offers/Discounts and Enjoy African Flavored Hospitality.", + "url": "https://www.ethiopianairlines.com/", + "breadcrumb": "https://www.ethiopianairlines.com" + }, + { + "type": "organic", + "rank_group": 95, + "rank_absolute": 98, + "domain": "www.vietnamairlines.com", + "title": "Vietnam Airlines | Reach Further | Official website", + "description": "Great value fares with Vietnam Airlines. Book today and save! Skytrax – 4 Star airline. Official website. Earn frequent flyer miles with Lotusmiles.", + "url": "https://www.vietnamairlines.com/", + "breadcrumb": "https://www.vietnamairlines.com" + }, + { + "type": "organic", + "rank_group": 96, + "rank_absolute": 99, + "domain": "books.google.com", + "title": "Code of Federal Regulations: 1985-1999", + "description": "A purchases in New York a round-trip ticket for transportation by air from New York to ... B purchases a ticket in San Francisco for Combination rail and water ...", + "url": "https://books.google.com/books?id=av3umFsqbAEC&pg=PA305&lpg=PA305&dq=flight+ticket+new+york+san+francisco&source=bl&ots=fJJY5RUS9l&sig=ACfU3U16ejUqNf23jHD32QNCxDCa05Vn9g&hl=en&ppis=_e&sa=X&ved=2ahUKEwjs_4OnouzlAhXJ4zgGHeBcD3oQ6AEwdXoECHEQAQ", + "breadcrumb": "https://books.google.com › books" + } + ] + } + ] + } + ] +} diff --git a/priv/fixtures/serp/google/organic/task-post-single.json b/priv/fixtures/serp/google/organic/task-post-single.json new file mode 100644 index 0000000..49264a9 --- /dev/null +++ b/priv/fixtures/serp/google/organic/task-post-single.json @@ -0,0 +1,38 @@ +{ + "version": "0.1.20200129", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0818 sec.", + "cost": 0.0045, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "01291721-1535-0066-0000-8f0635c0dc89", + "status_code": 20100, + "status_message": "Task Created.", + "time": "0.0038 sec.", + "cost": 0.0015, + "result_count": 0, + "path": [ + "v3", + "serp", + "google", + "organic", + "task_post" + ], + "data": { + "api": "serp", + "function": "task_post", + "se": "google", + "se_type": "organic", + "language_code": "en", + "location_code": 2840, + "keyword": "Schrauben", + "device": "desktop", + "os": "windows" + }, + "result": null + } + ] +} diff --git a/priv/fixtures/serp/google/organic/task-post.json b/priv/fixtures/serp/google/organic/task-post.json new file mode 100644 index 0000000..fbc58ab --- /dev/null +++ b/priv/fixtures/serp/google/organic/task-post.json @@ -0,0 +1,68 @@ +{ + "version": "0.1.20200129", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0818 sec.", + "cost": 0.0045, + "tasks_count": 2, + "tasks_error": 0, + "tasks": [ + { + "id": "01291721-1535-0066-0000-8f0635c0dc89", + "status_code": 20100, + "status_message": "Task Created.", + "time": "0.0038 sec.", + "cost": 0.0015, + "result_count": 0, + "path": [ + "v3", + "serp", + "google", + "organic", + "task_post" + ], + "data": { + "api": "serp", + "function": "task_post", + "se": "google", + "se_type": "organic", + "language_code": "en", + "location_code": 2840, + "keyword": "Schrauben", + "device": "desktop", + "os": "windows" + }, + "result": null + }, + { + "id": "01291721-1535-0066-0000-2e7a8bf7302c", + "status_code": 20100, + "status_message": "Task Created.", + "time": "0.0050 sec.", + "cost": 0.0015, + "result_count": 0, + "path": [ + "v3", + "serp", + "google", + "organic", + "task_post" + ], + "data": { + "api": "serp", + "function": "task_post", + "se": "google", + "se_type": "organic", + "language_name": "English", + "location_name": "United States", + "keyword": "Blumen", + "priority":2, + "pingback_url": "https://your-server.com/pingscript?id=$id&tag=$tag", + "tag": "some_string_123", + "device": "desktop", + "os": "windows" + }, + "result": null + } + ] +} diff --git a/priv/fixtures/serp/google/organic/tasks-ready.json b/priv/fixtures/serp/google/organic/tasks-ready.json new file mode 100644 index 0000000..40d71eb --- /dev/null +++ b/priv/fixtures/serp/google/organic/tasks-ready.json @@ -0,0 +1,52 @@ +{ + "version": "0.1.20200129", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.2270 sec.", + "cost": 0, + "tasks_count": 1, + "tasks_error": 0, + "tasks": [ + { + "id": "11151406-0696-0087-0000-e781cb0144a1", + "status_code": 20000, + "status_message": "Ok.", + "time": "0.0388 sec.", + "cost": 0, + "result_count": 2, + "path": [ + "v3", + "serp", + "google", + "organic", + "tasks_ready" + ], + "data": { + "api": "serp", + "function": "tasks_ready", + "se": "google", + "se_type": "organic" + }, + "result": [ + { + "id": "11081554-0696-0066-0000-27e68ec15871", + "se": "google", + "se_type": "organic", + "date_posted": "2019-11-08 13:54:43 +00:00", + "endpoint_regular": "/v3/serp/google/organic/task_get/regular/11081554-0696-0066-0000-27e68ec15871", + "endpoint_advanced": "/v3/serp/google/organic/task_get/advanced/11081554-0696-0066-0000-27e68ec15871", + "endpoint_html": "/v3/serp/google/organic/task_get/html/11081554-0696-0066-0000-27e68ec15871" + }, + { + "id": "11151406-0696-0066-0000-c4ece317cdb2", + "se": "google", + "se_type": "organic", + "date_posted": "2019-11-15 12:06:09 +00:00", + "endpoint_regular": "/v3/serp/google/organic/task_get/regular/11151406-0696-0066-0000-c4ece317cdb2", + "endpoint_advanced": "/v3/serp/google/organic/task_get/advanced/11081554-0696-0066-0000-27e68ec15871", + "endpoint_html": "/v3/serp/google/organic/task_get/html/11151406-0696-0066-0000-c4ece317cdb2" + } + ] + } + ] +} diff --git a/test/data_for_seo/api/keywords/google_trends/languages_test.exs b/test/data_for_seo/api/keywords/google_trends/languages_test.exs index d4f4097..9ac2b02 100644 --- a/test/data_for_seo/api/keywords/google_trends/languages_test.exs +++ b/test/data_for_seo/api/keywords/google_trends/languages_test.exs @@ -24,7 +24,7 @@ defmodule DataForSeo.Api.Keywords.GoogleTrends.LanguagesTest do Plug.Conn.resp( conn, 200, - task_get_google_trend_languages() + task_get_google_trends_languages() ) end) diff --git a/test/data_for_seo/api/labs/google/categories_test.exs b/test/data_for_seo/api/labs/google/categories_test.exs index 44d40b3..afb4e80 100644 --- a/test/data_for_seo/api/labs/google/categories_test.exs +++ b/test/data_for_seo/api/labs/google/categories_test.exs @@ -24,7 +24,7 @@ defmodule DataForSeo.Api.Labs.Google.CategoriesTest do Plug.Conn.resp( conn, 200, - task_get_google_categories() + task_get_labs_google_categories() ) end) diff --git a/test/data_for_seo/api/location_test.exs b/test/data_for_seo/api/serp/google/location_test.exs similarity index 88% rename from test/data_for_seo/api/location_test.exs rename to test/data_for_seo/api/serp/google/location_test.exs index b9eeccf..51a6b28 100644 --- a/test/data_for_seo/api/location_test.exs +++ b/test/data_for_seo/api/serp/google/location_test.exs @@ -1,7 +1,7 @@ -defmodule DataForSeo.Api.LocationTest do +defmodule DataForSeo.Api.SERP.Google.LocationTest do use ExUnit.Case - alias DataForSeo.API.SERP.Location + alias DataForSeo.API.SERP.Google.Location import RespFactory @@ -24,7 +24,7 @@ defmodule DataForSeo.Api.LocationTest do Plug.Conn.resp( conn, 200, - task_get_location_by_country() + task_get_location_by_country("lu") ) end) diff --git a/test/support/resp_factory.ex b/test/support/resp_factory.ex index 6c2b3c4..2e7ee1c 100644 --- a/test/support/resp_factory.ex +++ b/test/support/resp_factory.ex @@ -1,832 +1,65 @@ defmodule RespFactory do def task_post_single_response do - """ - { - "version": "0.1.20200129", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0818 sec.", - "cost": 0.0045, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "01291721-1535-0066-0000-8f0635c0dc89", - "status_code": 20100, - "status_message": "Task Created.", - "time": "0.0038 sec.", - "cost": 0.0015, - "result_count": 0, - "path": [ - "v3", - "serp", - "google", - "organic", - "task_post" - ], - "data": { - "api": "serp", - "function": "task_post", - "se": "google", - "se_type": "organic", - "language_code": "en", - "location_code": 2840, - "keyword": "Schrauben", - "device": "desktop", - "os": "windows" - }, - "result": null - } - ] - } - """ + get_raw_fixture(["serp", "google", "organic", "task-post-single"]) end def task_post_list_response do - """ - { - "version": "0.1.20200129", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0818 sec.", - "cost": 0.0045, - "tasks_count": 2, - "tasks_error": 0, - "tasks": [ - { - "id": "01291721-1535-0066-0000-8f0635c0dc89", - "status_code": 20100, - "status_message": "Task Created.", - "time": "0.0038 sec.", - "cost": 0.0015, - "result_count": 0, - "path": [ - "v3", - "serp", - "google", - "organic", - "task_post" - ], - "data": { - "api": "serp", - "function": "task_post", - "se": "google", - "se_type": "organic", - "language_code": "en", - "location_code": 2840, - "keyword": "Schrauben", - "device": "desktop", - "os": "windows" - }, - "result": null - }, - { - "id": "01291721-1535-0066-0000-2e7a8bf7302c", - "status_code": 20100, - "status_message": "Task Created.", - "time": "0.0050 sec.", - "cost": 0.0015, - "result_count": 0, - "path": [ - "v3", - "serp", - "google", - "organic", - "task_post" - ], - "data": { - "api": "serp", - "function": "task_post", - "se": "google", - "se_type": "organic", - "language_name": "English", - "location_name": "United States", - "keyword": "Blumen", - "priority":2, - "pingback_url": "https://your-server.com/pingscript?id=$id&tag=$tag", - "tag": "some_string_123", - "device": "desktop", - "os": "windows" - }, - "result": null - } - ] - } - """ + get_raw_fixture(["serp", "google", "organic", "task-post"]) end def tasks_ready_response do - """ - { - "version": "0.1.20200129", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.2270 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "11151406-0696-0087-0000-e781cb0144a1", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0388 sec.", - "cost": 0, - "result_count": 2, - "path": [ - "v3", - "serp", - "google", - "organic", - "tasks_ready" - ], - "data": { - "api": "serp", - "function": "tasks_ready", - "se": "google", - "se_type": "organic" - }, - "result": [ - { - "id": "11081554-0696-0066-0000-27e68ec15871", - "se": "google", - "se_type": "organic", - "date_posted": "2019-11-08 13:54:43 +00:00", - "endpoint_regular": "/v3/serp/google/organic/task_get/regular/11081554-0696-0066-0000-27e68ec15871", - "endpoint_advanced": "/v3/serp/google/organic/task_get/advanced/11081554-0696-0066-0000-27e68ec15871", - "endpoint_html": "/v3/serp/google/organic/task_get/html/11081554-0696-0066-0000-27e68ec15871" - }, - { - "id": "11151406-0696-0066-0000-c4ece317cdb2", - "se": "google", - "se_type": "organic", - "date_posted": "2019-11-15 12:06:09 +00:00", - "endpoint_regular": "/v3/serp/google/organic/task_get/regular/11151406-0696-0066-0000-c4ece317cdb2", - "endpoint_advanced": "/v3/serp/google/organic/task_get/advanced/11081554-0696-0066-0000-27e68ec15871", - "endpoint_html": "/v3/serp/google/organic/task_get/html/11151406-0696-0066-0000-c4ece317cdb2" - } - ] - } - ] - } - """ + get_raw_fixture(["serp", "google", "organic", "tasks-ready"]) end def task_result_response do - """ - { - "version": "0.1.20200129", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.3059 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "11151456-0696-0066-0000-002a5915da37", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0952 sec.", - "cost": 0, - "result_count": 1, - "path": [ - "v3", - "serp", - "google", - "organic", - "task_get", - "regular", - "11151456-0696-0066-0000-002a5915da37" - ], - "data": { - "api": "serp", - "function": "task_get", - "se": "google", - "se_type": "organic", - "language_name": "English", - "location_name": "United States", - "keyword": "flight ticket new york san francisco", - "priority": "2", - "tag": "tag2", - "device": "desktop", - "os": "windows" - }, - "result": [ - { - "keyword": "flight ticket new york san francisco", - "type": "organic", - "se_domain": "google.com", - "location_code": 2840, - "language_code": "en", - "check_url": "https://www.google.com/search?q=flight%20ticket%20new%20york%20san%20francisco&num=100&hl=en&gl=US&gws_rd=cr&ie=UTF-8&oe=UTF-8&uule=w+CAIQIFISCQs2MuSEtepUEUK33kOSuTsc", - "datetime": "2019-11-15 12:57:46 +00:00", - "spell": null, - "item_types": [ - "organic", - "paid" - ], - "se_results_count": 85600000, - "items_count": 96, - "items": [ - { - "type": "paid", - "rank_group": 1, - "rank_absolute": 1, - "domain": "www.bookingbuddy.com", - "title": "Flights To Lwo | Unbelievably Cheap Flights | BookingBuddy.com‎", - "description": "Compare Airlines & Sites. Cheap Flights on BookingBuddy, a TripAdvisor Company", - "url": "https://www.bookingbuddy.com/en/hero/", - "breadcrumb": "www.bookingbuddy.com/Flights" - }, - { - "type": "paid", - "rank_group": 2, - "rank_absolute": 2, - "domain": "www.trip.com", - "title": "Cheap Flight Tickets | Search & Find Deals on Flights | trip.com‎", - "description": "Wide Selection of Cheap Flights Online. Explore & Save with Trip.com! Fast, Easy & Secure...", - "url": "https://www.trip.com/flights/index?utm_campaign=GG_SE_All_en_Flight_Generic_NA_Phrase", - "breadcrumb": "www.trip.com/" - }, - { - "type": "paid", - "rank_group": 3, - "rank_absolute": 4, - "domain": "www.kayak.com", - "title": "Find the Cheapest Flights | Search, Compare & Save Today‎", - "description": "Cheap Flights, Airline Tickets and Flight Deals. Compare 100s of Airlines Worldwide. Search...", - "url": "https://www.kayak.com/horizon/sem/flights/general", - "breadcrumb": "www.kayak.com/flights" - }, - { - "type": "organic", - "rank_group": 1, - "rank_absolute": 5, - "domain": "www.kayak.com", - "title": "Cheap Flights from New York to San Francisco from $182 ...", - "description": "Fly from New York to San Francisco on Frontier from $182, United Airlines from ... the cheapest round-trip tickets were found on Frontier ($182), United Airlines ...", - "url": "https://www.kayak.com/flight-routes/New-York-NYC/San-Francisco-SFO", - "breadcrumb": "https://www.kayak.com › Flights › North America › United States › California" - }, - { - "type": "organic", - "rank_group": 2, - "rank_absolute": 6, - "domain": "www.skyscanner.com", - "title": "Cheap flights from New York to San Francisco SFO from $123 ...", - "description": "Flight information New York to San Francisco International .... tool will help you find the cheapest tickets from New York in San Francisco in just a few clicks.", - "url": "https://www.skyscanner.com/routes/nyca/sfo/new-york-to-san-francisco-international.html", - "breadcrumb": "https://www.skyscanner.com › United States › New York" - }, - { - "type": "organic", - "rank_group": 3, - "rank_absolute": 7, - "domain": "www.expedia.com", - "title": "JFK to SFO: Flights from New York to San Francisco for 2019 ...", - "description": "Book your New York (JFK) to San Francisco (SFO) flight with our Best Price ... How much is a plane ticket to San Francisco (SFO) from New York (JFK)?.", - "url": "https://www.expedia.com/lp/flights/jfk/sfo/new-york-to-san-francisco", - "breadcrumb": "https://www.expedia.com › flights › jfk › sfo › new-york-to-san-francisco" - }, - { - "type": "organic", - "rank_group": 94, - "rank_absolute": 97, - "domain": "www.ethiopianairlines.com", - "title": "Ethiopian Airlines | Book your next flight online and Fly Ethiopian", - "description": "Fly to your Favorite International Destination with Ethiopian Airlines. Book your Flights Online for Best Offers/Discounts and Enjoy African Flavored Hospitality.", - "url": "https://www.ethiopianairlines.com/", - "breadcrumb": "https://www.ethiopianairlines.com" - }, - { - "type": "organic", - "rank_group": 95, - "rank_absolute": 98, - "domain": "www.vietnamairlines.com", - "title": "Vietnam Airlines | Reach Further | Official website", - "description": "Great value fares with Vietnam Airlines. Book today and save! Skytrax – 4 Star airline. Official website. Earn frequent flyer miles with Lotusmiles.", - "url": "https://www.vietnamairlines.com/", - "breadcrumb": "https://www.vietnamairlines.com" - }, - { - "type": "organic", - "rank_group": 96, - "rank_absolute": 99, - "domain": "books.google.com", - "title": "Code of Federal Regulations: 1985-1999", - "description": "A purchases in New York a round-trip ticket for transportation by air from New York to ... B purchases a ticket in San Francisco for Combination rail and water ...", - "url": "https://books.google.com/books?id=av3umFsqbAEC&pg=PA305&lpg=PA305&dq=flight+ticket+new+york+san+francisco&source=bl&ots=fJJY5RUS9l&sig=ACfU3U16ejUqNf23jHD32QNCxDCa05Vn9g&hl=en&ppis=_e&sa=X&ved=2ahUKEwjs_4OnouzlAhXJ4zgGHeBcD3oQ6AEwdXoECHEQAQ", - "breadcrumb": "https://books.google.com › books" - } - ] - } - ] - } - ] - } - """ + get_raw_fixture(["serp", "google", "organic", "task-get"]) end - def task_get_location_by_country do - """ - { - "cost": 0, - "status_code": 20000, - "status_message": "Ok.", - "tasks_count": 1, - "tasks_error": 0, - "time": "0.0629 sec.", - "version": "0.1.20230825", - "tasks": [ - { - "cost": 0, - "data": { - "api": "serp", - "function": "locations", - "se": "google" - }, - "id": "11151921-6990-0096-0000-383626e07f8a", - "path": [ - "v3", - "serp", - "google", - "locations", - "lu" - ], - "result": [ - { - "country_iso_code": "LU", - "location_code": 2442, - "location_code_parent": null, - "location_name": "Luxembourg", - "location_type": "Country" - }, - { - "country_iso_code": "LU", - "location_code": 1009944, - "location_code_parent": 2442, - "location_name": "Kaerjeng,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 1009948, - "location_code_parent": 2442, - "location_name": "Bissen,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 1009953, - "location_code_parent": 2442, - "location_name": "Kirchberg,Luxembourg", - "location_type": "Neighborhood" - }, - { - "country_iso_code": "LU", - "location_code": 1009955, - "location_code_parent": 2442, - "location_name": "Mamer,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 1009958, - "location_code_parent": 2442, - "location_name": "Sanem,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 1009960, - "location_code_parent": 2442, - "location_name": "Strassen,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 1009964, - "location_code_parent": 2442, - "location_name": "Wormeldange,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067741, - "location_code_parent": 2442, - "location_name": "Clemency,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067742, - "location_code_parent": 2442, - "location_name": "Wiltz,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067743, - "location_code_parent": 2442, - "location_name": "Troisvierges,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067744, - "location_code_parent": 2442, - "location_name": "Munsbach,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067745, - "location_code_parent": 2442, - "location_name": "Ettelbruck,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067746, - "location_code_parent": 2442, - "location_name": "Bertrange,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067747, - "location_code_parent": 2442, - "location_name": "Bettembourg,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067748, - "location_code_parent": 2442, - "location_name": "Dudelange,Luxembourg", - "location_type": "City" - }, - { - "country_iso_code": "LU", - "location_code": 9067749, - "location_code_parent": 2442, - "location_name": "Luxembourg,Luxembourg", - "location_type": "City" - } - ], - "result_count": 17, - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0058 sec." - } - ] - } - """ + def task_get_location_by_country(code) do + get_raw_fixture(["serp", "google", "locations-#{code}"]) end - def task_get_google_categories do - """ - { - "version": "0.1.20200305", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0594 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "03061224-1535-0197-0000-4d85996ce1db", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0015 sec.", - "cost": 0, - "result_count": 3180, - "path": [ - "v3", - "dataforseo_labs", - "categories" - ], - "data": { - "api": "dataforseo_labs", - "function": "categories" - }, - "result": [ - { - "category_code": 10021, - "category_name": "Apparel", - "category_code_parent": null - }, - { - "category_code": 10178, - "category_name": "Apparel Accessories", - "category_code_parent": 10021 - }, - { - "category_code": 10937, - "category_name": "Bags & Packs", - "category_code_parent": 10178 - }, - { - "category_code": 12262, - "category_name": "Backpacks & Utility Bags", - "category_code_parent": 10937 - } - ] - } - ] - } - """ + def task_get_labs_google_categories do + get_raw_fixture(["labs", "google", "categories"]) end def task_get_google_trends_categories do - task_get_google_categories() + get_raw_fixture(["keywords", "google_trends", "categories"]) end - def task_get_google_trend_languages do - """ - { - "version": "0.1.20200408", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.1977 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "04081302-1535-0119-0000-cf474e770569", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0002 sec.", - "cost": 0, - "result_count": 231, - "path": [ - "v3", - "keywords_data", - "google_trends", - "languages" - ], - "data": { - "api": "keywords_data", - "function": "languages", - "se": "google_trends" - }, - "result": [ - { - "language_name": "Afrikaans", - "language_code": "af" - }, - { - "language_name": "Albanian", - "language_code": "sq" - }, - { - "language_name": "English", - "language_code": "en" - }, - { - "language_name": "German", - "language_code": "de" - } - ] - } - ] - } - """ + def task_get_google_trends_languages do + get_raw_fixture(["keywords", "google_trends", "languages"]) end def task_get_google_trend_locations do - """ - { - "version": "0.1.20210917", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.1012 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "09201832-1535-0120-0000-012e5cc7e0d9", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0244 sec.", - "cost": 0, - "result_count": 2383, - "path": [ - "v3", - "keywords_data", - "google_trends", - "locations" - ], - "data": { - "api": "keywords_data", - "function": "locations", - "se": "google_trends" - }, - "result": [ - { - "location_code": 2004, - "location_name": "Afghanistan", - "location_code_parent": null, - "country_iso_code": "AF", - "location_type": "Country", - "geo_name": "Afghanistan", - "geo_id": "AF" - }, - { - "location_code": 2008, - "location_name": "Albania", - "location_code_parent": null, - "country_iso_code": "AL", - "location_type": "Country", - "geo_name": "Albania", - "geo_id": "AL" - }, - { - "location_code": 2010, - "location_name": "Antarctica", - "location_code_parent": null, - "country_iso_code": "AQ", - "location_type": "Country", - "geo_name": "Antarctica", - "geo_id": "AQ" - }, - { - "location_code": 2012, - "location_name": "Algeria", - "location_code_parent": null, - "country_iso_code": "DZ", - "location_type": "Country", - "geo_name": "Algeria", - "geo_id": "DZ" - }, - { - "location_code": 2016, - "location_name": "American Samoa", - "location_code_parent": null, - "country_iso_code": "AS", - "location_type": "Country", - "geo_name": "American Samoa", - "geo_id": "AS" - }, - { - "location_code": 2020, - "location_name": "Andorra", - "location_code_parent": null, - "country_iso_code": "AD", - "location_type": "Country", - "geo_name": "Andorra", - "geo_id": "AD" - }, - { - "location_code": 2024, - "location_name": "Angola", - "location_code_parent": null, - "country_iso_code": "AO", - "location_type": "Country", - "geo_name": "Angola", - "geo_id": "AO" - }, - { - "location_code": 21113, - "location_name": "Donetsk Oblast,Ukraine", - "location_code_parent": 2804, - "country_iso_code": "UA", - "location_type": "Region", - "geo_name": "Donetsk Oblast,Ukraine", - "geo_id": "Donetsk Oblast,Ukraine" - } - ] - } - ] - } - """ + get_raw_fixture(["keywords", "google_trends", "locations"]) end def task_get_google_trend_locations_by_country(_) do # same fixture at the moment b/c there are no difference with all locations list # only testing a success routing to the url and response format - task_get_google_trend_locations() + get_raw_fixture(["keywords", "google_trends", "locations"]) end def task_get_google_ads_locations do - """ - { - "version": "3.20191128", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.4305 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "11061103-0696-0120-0000-268044305ce6", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.2547 sec.", - "cost": 0, - "result_count": 94933, - "path": [ - "v3", - "keywords_data", - "google_ads", - "locations" - ], - "data": { - "api": "keywords_data", - "function": "locations", - "se": "google_ads" - }, - "result": [ - { - "location_code": 2840, - "location_name": "United States", - "location_code_parent": null, - "country_iso_code": "US", - "location_type": "Country" - }, - { - "location_code": 21132, - "location_name": "Alaska,United States", - "location_code_parent": 2840, - "country_iso_code": "US", - "location_type": "State" - }, - { - "location_code": 21133, - "location_name": "Alabama,United States", - "location_code_parent": 2840, - "country_iso_code": "US", - "location_type": "State" - }, - { - "location_code": 21135, - "location_name": "Arkansas,United States", - "location_code_parent": 2840, - "country_iso_code": "US", - "location_type": "State" - } - ] - } - ] - } - """ + get_raw_fixture(["keywords", "google_ads", "locations"]) end def task_get_google_ads_languages do - """ - { - "version": "3.20191128", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.1773 sec.", - "cost": 0, - "tasks_count": 1, - "tasks_error": 0, - "tasks": [ - { - "id": "11061103-0696-0119-0000-a74d6a2ce740", - "status_code": 20000, - "status_message": "Ok.", - "time": "0.0000 sec.", - "cost": 0, - "result_count": 43, - "path": [ - "v3", - "keywords_data", - "google_ads", - "languages" - ], - "data": { - "api": "keywords_data", - "function": "languages", - "se": "google_ads" - }, - "result": [ - { - "language_name": "Arabic", - "language_code": "ar" - }, - { - "language_name": "Bulgarian", - "language_code": "bg" - }, - { - "language_name": "Catalan", - "language_code": "ca" - }, - { - "language_name": "Croatian", - "language_code": "hr" - } - ] - } - ] - } - """ + get_raw_fixture(["keywords", "google_ads", "languages"]) + end + + def get_raw_fixture(path = [_ | _]) do + :data_for_seo + |> :code.priv_dir() + |> Path.join(Enum.join(["fixtures" | path], "/")) + |> Kernel.<>(".json") + |> File.read!() + end + + def get_json_fixture(path = [_ | _]) do + path + |> get_raw_fixture() + |> Jason.decode!() end end