Tasks C, H, I from the plan: - Forgiving API key validation: add Printify UUID format and Printful length validation, validate on blur for fast feedback, helpful error messages with specific guidance - External links UX: verified all external links use <.external_link> component with target="_blank", rel="noopener noreferrer", icon, and screen reader text - Input styling WCAG compliance: increase input border contrast from ~3.3:1 to ~4.5-5:1 across all theme moods (neutral, warm, cool, dark) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -61,15 +61,17 @@ defmodule Berrypod.KeyValidationTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "validate_provider_key/2" do
|
||||
test "accepts reasonable key" do
|
||||
assert {:ok, "abcdef1234567890abcdef"} =
|
||||
KeyValidation.validate_provider_key("abcdef1234567890abcdef", "printify")
|
||||
describe "validate_provider_key/2 - Printify" do
|
||||
@printify_uuid "12345678-1234-1234-1234-123456789012"
|
||||
|
||||
test "accepts valid UUID format key" do
|
||||
assert {:ok, @printify_uuid} =
|
||||
KeyValidation.validate_provider_key(@printify_uuid, "printify")
|
||||
end
|
||||
|
||||
test "strips whitespace" do
|
||||
assert {:ok, "abcdef1234567890abcdef"} =
|
||||
KeyValidation.validate_provider_key(" abcdef1234567890abcdef ", "printful")
|
||||
assert {:ok, @printify_uuid} =
|
||||
KeyValidation.validate_provider_key(" #{@printify_uuid} ", "printify")
|
||||
end
|
||||
|
||||
test "rejects empty key" do
|
||||
@@ -87,9 +89,41 @@ defmodule Berrypod.KeyValidationTest do
|
||||
assert msg =~ "too short"
|
||||
end
|
||||
|
||||
test "rejects too-long key" do
|
||||
long_key = String.duplicate("a", 50)
|
||||
assert {:error, msg} = KeyValidation.validate_provider_key(long_key, "printify")
|
||||
assert msg =~ "too long"
|
||||
end
|
||||
|
||||
test "gives helpful error for non-UUID format" do
|
||||
assert {:error, msg} =
|
||||
KeyValidation.validate_provider_key("12345678123412341234123456789012", "printify")
|
||||
|
||||
assert msg =~ "UUID format"
|
||||
end
|
||||
end
|
||||
|
||||
describe "validate_provider_key/2 - Printful" do
|
||||
test "accepts reasonable length key" do
|
||||
key = String.duplicate("x", 40)
|
||||
assert {:ok, ^key} = KeyValidation.validate_provider_key(key, "printful")
|
||||
end
|
||||
|
||||
test "strips whitespace" do
|
||||
key = String.duplicate("x", 40)
|
||||
assert {:ok, ^key} = KeyValidation.validate_provider_key(" #{key} ", "printful")
|
||||
end
|
||||
|
||||
test "rejects too-short key" do
|
||||
assert {:error, msg} = KeyValidation.validate_provider_key("short", "printful")
|
||||
assert msg =~ "too short"
|
||||
end
|
||||
end
|
||||
|
||||
describe "validate_provider_key/2 - generic" do
|
||||
test "works without provider type" do
|
||||
assert {:ok, "abcdef1234567890abcdef"} =
|
||||
KeyValidation.validate_provider_key("abcdef1234567890abcdef")
|
||||
key = String.duplicate("x", 20)
|
||||
assert {:ok, ^key} = KeyValidation.validate_provider_key(key)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ defmodule BerrypodWeb.Admin.DashboardTest do
|
||||
|
||||
assert html =~ "Launch checklist"
|
||||
assert html =~ "Connect a print provider"
|
||||
assert html =~ "Connect Stripe"
|
||||
assert html =~ "Sync your products"
|
||||
assert html =~ "Customise your theme"
|
||||
assert html =~ "Connect Stripe for payments"
|
||||
assert html =~ "Import products"
|
||||
assert html =~ "Customise your shop"
|
||||
assert html =~ "Go live"
|
||||
end
|
||||
|
||||
@@ -43,16 +43,16 @@ defmodule BerrypodWeb.Admin.DashboardTest do
|
||||
|
||||
test "collapse and expand checklist", %{conn: conn} do
|
||||
{:ok, view, html} = live(conn, ~p"/admin")
|
||||
assert html =~ "Sync your products"
|
||||
assert html =~ "Import products"
|
||||
|
||||
# Collapse
|
||||
html = render_click(view, "toggle_checklist")
|
||||
refute html =~ "Sync your products"
|
||||
refute html =~ "Import products"
|
||||
assert html =~ "Launch checklist"
|
||||
|
||||
# Expand
|
||||
html = render_click(view, "toggle_checklist")
|
||||
assert html =~ "Sync your products"
|
||||
assert html =~ "Import products"
|
||||
end
|
||||
|
||||
test "go live button works", %{conn: conn} do
|
||||
|
||||
@@ -174,11 +174,14 @@ defmodule BerrypodWeb.Admin.ProvidersTest do
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
# Printify uses 36-character UUID format keys
|
||||
valid_uuid_key = "12345678-1234-1234-1234-123456789012"
|
||||
|
||||
{:ok, _view, html} =
|
||||
view
|
||||
|> form("#provider-form", %{
|
||||
"provider_connection" => %{
|
||||
"api_key" => "test_key_123"
|
||||
"api_key" => valid_uuid_key
|
||||
}
|
||||
})
|
||||
|> render_submit()
|
||||
|
||||
@@ -57,12 +57,13 @@ defmodule BerrypodWeb.Setup.OnboardingTest do
|
||||
end
|
||||
|
||||
describe "fresh install (no admin)" do
|
||||
test "shows all three cards with email form active", %{conn: conn} do
|
||||
test "shows only account card (simplified setup)", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/setup")
|
||||
|
||||
assert html =~ "Set up your account"
|
||||
assert html =~ "Connect a print provider"
|
||||
assert html =~ "Connect payments"
|
||||
# Provider and Stripe cards are hidden until after account creation
|
||||
refute html =~ "Connect a print provider"
|
||||
refute html =~ "Connect payments"
|
||||
end
|
||||
|
||||
test "creating account auto-confirms and redirects to login", %{conn: conn} do
|
||||
@@ -73,7 +74,8 @@ defmodule BerrypodWeb.Setup.OnboardingTest do
|
||||
account: %{
|
||||
shop_name: "Test Shop",
|
||||
email: "admin@example.com",
|
||||
password: "valid_password_123"
|
||||
password: "valid_password_123",
|
||||
password_confirmation: "valid_password_123"
|
||||
}
|
||||
)
|
||||
|> render_submit()
|
||||
@@ -87,26 +89,31 @@ defmodule BerrypodWeb.Setup.OnboardingTest do
|
||||
describe "configure (logged in)" do
|
||||
setup :register_and_log_in_user
|
||||
|
||||
test "shows provider and stripe steps", %{conn: conn, user: user} do
|
||||
test "shows guided setup flow", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/setup")
|
||||
|
||||
assert html =~ user.email
|
||||
assert html =~ "Connect a print provider"
|
||||
assert html =~ "Connect payments"
|
||||
# Guided flow shows progress bar
|
||||
assert html =~ "Setup progress"
|
||||
# Shows one of the setup steps or intro
|
||||
assert html =~ "Connect" or html =~ "Let's get started"
|
||||
end
|
||||
|
||||
test "shows provider cards", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/setup")
|
||||
test "clicking start shows provider step", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/setup")
|
||||
|
||||
html = render_click(view, "start_setup")
|
||||
|
||||
assert html =~ "Connect a print provider"
|
||||
assert html =~ "Printify"
|
||||
assert html =~ "Printful"
|
||||
assert html =~ "Gelato"
|
||||
assert html =~ "Coming soon"
|
||||
end
|
||||
|
||||
test "selecting a provider shows the API key form", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/setup")
|
||||
|
||||
# First go to provider step
|
||||
render_click(view, "start_setup")
|
||||
|
||||
html =
|
||||
view
|
||||
|> form(~s(form[phx-change="select_provider"]), %{provider_select: %{type: "printify"}})
|
||||
@@ -116,11 +123,15 @@ defmodule BerrypodWeb.Setup.OnboardingTest do
|
||||
assert html =~ "Printify"
|
||||
end
|
||||
|
||||
test "shows stripe form", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/setup")
|
||||
test "skipping provider step shows stripe step", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/setup")
|
||||
|
||||
# Start and skip provider
|
||||
render_click(view, "start_setup")
|
||||
html = render_click(view, "skip_step")
|
||||
|
||||
assert html =~ "Secret key"
|
||||
assert html =~ "Connect payments"
|
||||
assert html =~ "Connect Stripe"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user