test/openagents/forum/legacy_surface_test.exs

58e6347eeb72 · 5 KB

defmodule OpenAgents.Forum.LegacySurfaceTest do
  @moduledoc """
  #23: what the cutover from the legacy forum has to keep true.

  Three claims, all of which used to live only in prose. The forge no longer
  reads the legacy mirror, a link written against the legacy surface still
  lands on the topic it named, and the page that tells a reader how to use the
  forum agrees with the authority the router actually applies.
  """

  use OpenAgents.DataCase, async: true

  alias OpenAgents.Forum
  alias OpenAgentsWeb.RouteAuthority

  # The mirror's own identifiers. The bare word also appears in seeded
  # changelog copy about an unrelated governance chain, which is prose rather
  # than a dependency, so the pattern names the database, its role, and its
  # Cloud SQL instance instead.
  @mirror ~r/khala_sync_prod|khala_app|khala-sync-pg/i

  # The one-time import. It is a Mix task: it needs `FORUM_IMPORT_*` in the
  # environment, nothing in the application calls it, and `Mix` is not loaded
  # in a release, so it cannot run on a served node.
  @import_task "lib/mix/tasks/openagents.forum.import.ex"

  describe "the legacy mirror" do
    test "is named nowhere the running application can reach" do
      offenders =
        (Path.wildcard("lib/**/*.{ex,exs}") ++ Path.wildcard("config/**/*.exs"))
        |> Enum.reject(&(&1 == @import_task))
        |> Enum.filter(&Regex.match?(@mirror, File.read!(&1)))

      assert offenders == [],
             "the legacy forum mirror is still named outside the one-time import task: " <>
               Enum.join(offenders, ", ")
    end

    test "is named in the import task, which is a Mix task and not application code" do
      source = File.read!(@import_task)

      assert Regex.match?(@mirror, source),
             "the import task no longer names its source; move this test or delete it"

      assert source =~ "use Mix.Task"
    end

    test "is not a repository this application starts" do
      assert Application.get_env(:openagents, :ecto_repos) == [OpenAgents.Repo]
    end
  end

  describe "legacy links" do
    setup do
      # The import wrote each legacy row's own UUID into the primary key, which
      # is what makes the redirect map an identity rather than a table.
      legacy_board = "1b4f0e98-4b1f-4a2a-9c3d-000000000023"
      legacy_topic = "2c5f1e98-4b1f-4a2a-9c3d-000000000023"

      board =
        Repo.insert!(%Forum.Forum{
          id: legacy_board,
          slug: "product-promises",
          title: "Product promises",
          visibility: "public",
          discoverability: "listed"
        })

      topic =
        Repo.insert!(%Forum.Topic{
          id: legacy_topic,
          forum_id: board.id,
          idempotency_key: "legacy-topic-#{legacy_topic}",
          slug: "what-the-forge-promises",
          title: "What the forge promises",
          actor_ref: "agent:user_0123abcd",
          actor_display_name: "Artanis",
          state: "open",
          pin_state: "normal",
          created_at: DateTime.utc_now(),
          updated_at: DateTime.utc_now()
        })

      %{board: board, topic: topic}
    end

    test "a legacy topic id resolves to the topic it named", %{topic: topic} do
      assert {:ok, resolved} = Forum.fetch_readable_topic(topic.id, [])
      assert resolved.title == "What the forge promises"
    end

    test "a legacy board slug resolves to the board it named", %{board: board} do
      assert {:ok, resolved} = Forum.fetch_readable_forum_by_slug(board.slug, [])
      assert resolved.id == board.id
    end

    test "an anonymous reader resolves both, with no operator scope", %{
      board: board,
      topic: topic
    } do
      assert {:ok, _board} = Forum.fetch_readable_forum_by_slug(board.slug, operator?: false)
      assert {:ok, _topic} = Forum.fetch_readable_topic(topic.id, operator?: false)
    end
  end

  describe "the documentation a reader is given" do
    # The page served at `/docs/forum`. It went on telling people to sign in
    # before reading a surface anyone can reach, which sends a visitor to a
    # login wall to see something already in front of them.
    @page "priv/docs/forum.md"
    @sign_in ~r/sign in|signed in|sign-in|log in|logged in/i

    test "does not ask a reader to sign in for a route the router serves publicly" do
      route =
        Enum.find(RouteAuthority.inventory(), &(&1.verb == "get" and &1.path == "/forum"))

      assert route.class == :public_read,
             "`/forum` is no longer a public read; this file's claim about the docs " <>
               "page has to be re-decided rather than re-worded"

      refute Regex.match?(@sign_in, section(@page, "Reading")),
             "the forum documentation still asks a reader to sign in to read"
    end

    test "still says an account is what posting needs" do
      assert Regex.match?(@sign_in, section(@page, "Posting"))
    end

    # One `##` section of a Markdown page, without its heading.
    defp section(path, heading) do
      path
      |> File.read!()
      |> String.split(~r/^## /m)
      |> Enum.find(&String.starts_with?(&1, heading <> "\n"))
      |> String.replace_prefix(heading <> "\n", "")
    end
  end
end