Extract Products.connect_provider/2 that tests the connection, fetches shop_id, creates the record, and enqueues sync. Both the setup wizard and the providers form now use this shared function instead of duplicating the flow. Also makes the products empty state context-aware (distinguishes "no provider" from "provider connected but no products"). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
282 lines
7.8 KiB
Elixir
282 lines
7.8 KiB
Elixir
defmodule BerrypodWeb.Admin.ProvidersTest do
|
|
use BerrypodWeb.ConnCase, async: false
|
|
|
|
import Phoenix.LiveViewTest
|
|
import Berrypod.AccountsFixtures
|
|
import Berrypod.ProductsFixtures
|
|
import Mox
|
|
|
|
alias Berrypod.Providers.MockProvider
|
|
|
|
setup :verify_on_exit!
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
%{user: user}
|
|
end
|
|
|
|
# -- Index page --
|
|
|
|
describe "index - unauthenticated" do
|
|
test "redirects to login", %{conn: conn} do
|
|
{:error, redirect} = live(conn, ~p"/admin/providers")
|
|
assert {:redirect, %{to: path}} = redirect
|
|
assert path == ~p"/users/log-in"
|
|
end
|
|
end
|
|
|
|
describe "index - empty state" do
|
|
setup %{conn: conn, user: user} do
|
|
%{conn: log_in_user(conn, user)}
|
|
end
|
|
|
|
test "shows empty state when no connections exist", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert html =~ "Connect a print-on-demand provider"
|
|
end
|
|
|
|
test "shows connect buttons for both providers", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert has_element?(view, ~s(a[href="/admin/providers/new?type=printify"]))
|
|
assert has_element?(view, ~s(a[href="/admin/providers/new?type=printful"]))
|
|
end
|
|
end
|
|
|
|
describe "index - with connection" do
|
|
setup %{conn: conn, user: user} do
|
|
connection =
|
|
provider_connection_fixture(%{
|
|
provider_type: "printify",
|
|
name: "My Printify Shop"
|
|
})
|
|
|
|
%{conn: log_in_user(conn, user), connection: connection}
|
|
end
|
|
|
|
test "lists provider connections", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert html =~ "Printify"
|
|
assert html =~ "My Printify Shop"
|
|
end
|
|
|
|
test "shows edit link", %{conn: conn, connection: connection} do
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert has_element?(view, ~s(a[href="/admin/providers/#{connection.id}/edit"]))
|
|
end
|
|
|
|
test "shows product count", %{conn: conn, connection: connection} do
|
|
product_fixture(%{provider_connection: connection})
|
|
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert html =~ "1 product"
|
|
end
|
|
|
|
test "shows never synced warning", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
|
|
|
assert html =~ "Never synced"
|
|
end
|
|
end
|
|
|
|
describe "index - delete" do
|
|
setup %{conn: conn, user: user} do
|
|
connection =
|
|
provider_connection_fixture(%{
|
|
provider_type: "printify",
|
|
name: "Delete Me Shop"
|
|
})
|
|
|
|
%{conn: log_in_user(conn, user), connection: connection}
|
|
end
|
|
|
|
test "deletes connection and shows flash", %{conn: conn, connection: connection} do
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
|
|
|
html = render_click(view, "delete", %{"id" => to_string(connection.id)})
|
|
|
|
assert html =~ "Provider connection deleted"
|
|
refute html =~ "Delete Me Shop"
|
|
end
|
|
end
|
|
|
|
describe "index - sync" do
|
|
setup %{conn: conn, user: user} do
|
|
Application.put_env(:berrypod, :provider_modules, %{
|
|
"printify" => MockProvider
|
|
})
|
|
|
|
on_exit(fn -> Application.delete_env(:berrypod, :provider_modules) end)
|
|
|
|
connection =
|
|
provider_connection_fixture(%{
|
|
provider_type: "printify",
|
|
name: "Sync Test Shop"
|
|
})
|
|
|
|
%{conn: log_in_user(conn, user), connection: connection}
|
|
end
|
|
|
|
test "starts sync and shows flash", %{conn: conn, connection: connection} do
|
|
stub(MockProvider, :fetch_products, fn _conn -> {:ok, []} end)
|
|
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
|
|
|
html = render_click(view, "sync", %{"id" => to_string(connection.id)})
|
|
|
|
assert html =~ "Sync started"
|
|
end
|
|
end
|
|
|
|
# -- Form page --
|
|
|
|
describe "form - new" do
|
|
setup %{conn: conn, user: user} do
|
|
Application.put_env(:berrypod, :provider_modules, %{
|
|
"printify" => MockProvider
|
|
})
|
|
|
|
on_exit(fn -> Application.delete_env(:berrypod, :provider_modules) end)
|
|
|
|
%{conn: log_in_user(conn, user)}
|
|
end
|
|
|
|
test "renders new Printify form", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers/new?type=printify")
|
|
|
|
assert html =~ "Connect to Printify"
|
|
assert html =~ "Printify API key"
|
|
assert html =~ "Log in to Printify"
|
|
end
|
|
|
|
test "renders new Printful form", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers/new?type=printful")
|
|
|
|
assert html =~ "Connect to Printful"
|
|
assert html =~ "Printful API key"
|
|
assert html =~ "Log in to Printful"
|
|
end
|
|
|
|
test "defaults to Printify when no type param", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers/new")
|
|
|
|
assert html =~ "Connect to Printify"
|
|
end
|
|
|
|
test "test connection shows error when no api key", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
|
|
|
html = render_click(view, "test_connection")
|
|
|
|
assert html =~ "Please enter your API key"
|
|
end
|
|
|
|
test "saves new connection", %{conn: conn} do
|
|
expect(MockProvider, :test_connection, fn _conn ->
|
|
{:ok, %{shop_name: "My Printify Shop", shop_id: 12345}}
|
|
end)
|
|
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
|
|
|
{:ok, _view, html} =
|
|
view
|
|
|> form("#provider-form", %{
|
|
"provider_connection" => %{
|
|
"api_key" => "test_key_123"
|
|
}
|
|
})
|
|
|> render_submit()
|
|
|> follow_redirect(conn, ~p"/admin/settings")
|
|
|
|
assert html =~ "Connected to Printify"
|
|
end
|
|
end
|
|
|
|
describe "form - test connection" do
|
|
setup %{conn: conn, user: user} do
|
|
Application.put_env(:berrypod, :provider_modules, %{
|
|
"printify" => MockProvider
|
|
})
|
|
|
|
on_exit(fn -> Application.delete_env(:berrypod, :provider_modules) end)
|
|
|
|
%{conn: log_in_user(conn, user)}
|
|
end
|
|
|
|
test "shows success when connection is valid", %{conn: conn} do
|
|
expect(MockProvider, :test_connection, fn _conn ->
|
|
{:ok, %{shop_name: "My Printify Shop", shop_id: 12345}}
|
|
end)
|
|
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
|
|
|
# Validate first to set pending_api_key
|
|
view
|
|
|> form("#provider-form", %{
|
|
"provider_connection" => %{"api_key" => "valid_key_123"}
|
|
})
|
|
|> render_change()
|
|
|
|
html = render_click(view, "test_connection")
|
|
|
|
assert html =~ "Connected to My Printify Shop"
|
|
end
|
|
|
|
test "shows error when connection fails", %{conn: conn} do
|
|
expect(MockProvider, :test_connection, fn _conn ->
|
|
{:error, :unauthorized}
|
|
end)
|
|
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
|
|
|
view
|
|
|> form("#provider-form", %{
|
|
"provider_connection" => %{"api_key" => "bad_key"}
|
|
})
|
|
|> render_change()
|
|
|
|
html = render_click(view, "test_connection")
|
|
|
|
assert html =~ "doesn't seem to be valid"
|
|
end
|
|
end
|
|
|
|
describe "form - edit" do
|
|
setup %{conn: conn, user: user} do
|
|
connection =
|
|
provider_connection_fixture(%{
|
|
provider_type: "printify",
|
|
name: "Edit Me Shop"
|
|
})
|
|
|
|
%{conn: log_in_user(conn, user), connection: connection}
|
|
end
|
|
|
|
test "renders edit form", %{conn: conn, connection: connection} do
|
|
{:ok, _view, html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")
|
|
|
|
assert html =~ "Printify settings"
|
|
assert html =~ "Connection enabled"
|
|
assert html =~ "Save changes"
|
|
end
|
|
|
|
test "saves changes", %{conn: conn, connection: connection} do
|
|
{:ok, view, _html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")
|
|
|
|
{:ok, _view, html} =
|
|
view
|
|
|> form("#provider-form", %{
|
|
"provider_connection" => %{"enabled" => "true"}
|
|
})
|
|
|> render_submit()
|
|
|> follow_redirect(conn, ~p"/admin/settings")
|
|
|
|
assert html =~ "Settings saved"
|
|
end
|
|
end
|
|
end
|