packages feed

snippet-0.0.0.0: test/Snippet/LinesSpec.hs

-- |
--
-- Module      : Snippet.LinesSpec
-- Copyright   : (c) 2026 Patrick Brisbin
-- License     : AGPL-3
-- Maintainer  : pbrisbin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
module Snippet.LinesSpec
  ( spec
  ) where

import Prelude

import Control.Monad (guard)
import Data.List.NonEmpty qualified as NE
import Data.Text (Text, unpack)
import Data.Text qualified as T
import Snippet.Line
import Snippet.Lines
import Snippet.Region
import Test.Hspec

spec :: Spec
spec = do
  describe "makeLines" $ do
    it "handles a single-line case" $ do
      let
        region =
          Region
            { startLine = 85
            , startColumn = Just 9
            , endLine = Just 85
            , endColumn = Just 46
            }
        input =
          NE.fromList
            [ "      [ ((annotate AnnIcon xyz <+>) . pretty) <$> r"
            ]

      makeLines region input
        `shouldBe` NE.fromList
          [ l "85|      [ |((annotate AnnIcon xyz <+>) . pretty)| <$> r"
          , l "  |        |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
          ]

    it "handles a multi-line case" $ do
      let
        region =
          Region
            { startLine = 15
            , startColumn = Just 1
            , endLine = Just 18
            , endColumn = Just 22
            }

        input =
          NE.fromList
            [ "data ArtifactLocation = ArtifactLocation"
            , "  { uri :: Text"
            , "  }"
            , "  deriving stock (Eq)"
            ]

      makeLines region input
        `shouldBe` NE.fromList
          [ l "15||╭ data ArtifactLocation = ArtifactLocation"
          , l "16||│   { uri :: Text"
          , l "17||│   }"
          , l "18||│   deriving stock (Eq)"
          , l "  ||╰─────────────────────^"
          ]

    it "handles a complex multi-line case" $ do
      let
        region =
          Region
            { startLine = 15
            , startColumn = Just 6
            , endLine = Just 18
            , endColumn = Just 22
            }

        input =
          NE.fromList
            [ "data ArtifactLocation = ArtifactLocation"
            , "  { uri :: Text"
            , "  }"
            , "  deriving stock (Eq)"
            ]

      makeLines region input
        `shouldBe` NE.fromList
          [ l "15|  data |ArtifactLocation = ArtifactLocation"
          , l "  ||╭──────^"
          , l "16||│   { uri :: Text"
          , l "17||│   }"
          , l "18||│   deriving stock (Eq)"
          , l "  ||╰─────────────────────^"
          ]

-- | Micro-format to make expectations visually look like expected
l :: Text -> Line
l t = case T.splitOn "|" t of
  [nt, pre, focused, post] ->
    Line
      { number = do
          let n = T.strip nt
          guard $ not $ T.null n
          pure $ read $ unpack n
      , pre
      , focused
      , post
      }
  [nt, pre, focused] ->
    Line
      { number = do
          let n = T.strip nt
          guard $ not $ T.null n
          pure $ read $ unpack n
      , pre
      , focused
      , post = ""
      }
  x ->
    error
      $ "Expected line must be 3 or 4 parts delimited by \"|\". Saw "
        <> show (length x)
        <> "part(s): "
        <> show x