"""GET /marketplace/guide/{curated,flea} — submission flow guides. Both routes are authed (`get_current_user` dependency). The curated guide documents the Named Curator handoff and has a fast-path callout pointing at the flea self-service guide; the flea guide documents the /store/new upload flow. Together with the action-row CTA on /marketplace?tab=curated, this trio is the discovery surface for "how do I get my plugin published". """ from __future__ import annotations import tempfile import uuid import pytest @pytest.fixture def fresh_db(monkeypatch): with tempfile.TemporaryDirectory() as tmp: monkeypatch.setenv("DATA_DIR", tmp) monkeypatch.setenv("TESTING", "1") monkeypatch.setenv("JWT_SECRET_KEY", "test-jwt-secret-key-minimum-32-chars!!") yield tmp def _make_user_and_session(conn, email="u@example.com"): from src.repositories.users import UserRepository from app.auth.jwt import create_access_token uid = str(uuid.uuid4()) UserRepository(conn).create(id=uid, email=email, name=email.split("@")[0]) return uid, create_access_token(user_id=uid, email=email) def _client(): from fastapi.testclient import TestClient from app.main import app return TestClient(app) def test_marketplace_curated_tab_cta_text(fresh_db): """The action-row CTA on /marketplace?tab=curated reads 'Submit a skill or plugin' (renamed from 'Submit a plugin' so skills aren't an afterthought) and links to the curated guide. Empty-state fallback in JS uses the same string so both surfaces stay in sync.""" from src.db import get_system_db, close_system_db conn = get_system_db() try: _, sess = _make_user_and_session(conn) finally: conn.close() close_system_db() body = _client().get( "/marketplace?tab=curated", cookies={"access_token": sess} ).text # Action-row anchor — primary discovery path. assert ( 'Submit a skill or plugin' ) in body # Empty-state JS innerHTML — same string, no drift. assert "Submit a skill or plugin →" in body # Old wording must be gone — guards against partial rename. assert ">Submit a plugin<" not in body def test_marketplace_guide_curated_page(fresh_db): """Curated guide page documents the Named Curator handoff. Three-step flow (find → handoff → publish) lives inside `.guide-steps`. The fast-path callout points users at the flea guide as the lighter review-bar alternative; the primary CTA at the bottom does the same so users who skim past the callout still see the escape hatch.""" from src.db import get_system_db, close_system_db conn = get_system_db() try: _, sess = _make_user_and_session(conn) finally: conn.close() close_system_db() resp = _client().get( "/marketplace/guide/curated", cookies={"access_token": sess} ) assert resp.status_code == 200 body = resp.text # Title carries the new 'skill or plugin' wording. assert "Submit a skill or plugin to Curated Marketplace" in body # Lede surfaces the gatekeeping concept. assert "Named Curators" in body # Three-step ordered list under `.guide-steps`. assert '