packages feed

hmp3-ng-2.19.1: test/TextSpec.hs

module TextSpec (tests) where

import Test.Tasty
import Test.Tasty.HUnit

import Text

-- These tests depend on wcwidth's behavior under a UTF-8 locale and on a
-- handful of codepoints whose canonical widths are well-known:
--   * ASCII chars are 1 column.
--   * Latin-Extended chars (é, ñ) are 1 column.
--   * Common CJK chars (中) are 2 columns.
--   * The horizontal ellipsis (…) is 1 column.
-- They are not deterministic under the C locale.

tests :: TestTree
tests = testGroup "Text"
    [ testGroup "match"
        [ m (Just True)  "exact"         "foo"       "fooBar"
        , m (Just True)  "caseless"      "FOO"       "fooBar"
        , m Nothing      "invalid"       "["         "any[thing"
        , m (Just True)  "alt"           "(foo|az)Q" "bazQux"
        , m (Just True)  "dot"           "o.a"       "foobar"
        , m (Just True)  "Unicode"       "jör"       "Björk"
        , m (Just True)  "dot Unicode"   "j.r"       "Björk"
        , m (Just True)  "Nordic case"   "bør"       "BØrnE"
        , m (Just True)  "Greek case"    "Λω"        "ΦλΩα"
        , m (Just True)  "dot CJK"       "中.人"     "中國人"
        , m (Just False) "byte dots"     "c..te"     "côte"
        ]
    , testGroup "dropLastUTF8"
        [ testCase "ASCII"    $ dropLastUTF8 "abc"          @?= "ab"
        , testCase "empty"    $ dropLastUTF8 ""             @?= ""
        , testCase "French"   $ dropLastUTF8 (u"été")       @?= u"ét"
        , testCase "CJK"      $ dropLastUTF8 (u"中國")      @?= u"中"
        , testCase "Emoji"    $ dropLastUTF8 (u"Yes👍")     @?= u"Yes"
        , testCase "invalid"  $ dropLastUTF8 "\x80"         @?= ""
        ]
    , testGroup "trim"
        [ testCase "empty"      $ trim ""                   @?= ""
        , testCase "whitespace" $ trim "  \tfoo bar \n"     @?= "foo bar"
        ]
    , testGroup "guessEncoding"
        [ testCase "ASCII"    $ guessEncoding "abc"         @?= "abc"
        , testCase "ISO-8859" $ guessEncoding "encöde"      @?= u"encöde"
        , testCase "UTF-8"    $ guessEncoding (u"encöde")   @?= u"encöde"
        ]
    , testGroup "displayWidth"
        [ testCase "empty"             $ displayWidth ""              @?= 0
        , testCase "ascii"             $ displayWidth "hello"         @?= 5
        , testCase "latin-extended"    $ displayWidth (u"café")       @?= 4
        , testCase "cjk doubles each"  $ displayWidth (u"中文")       @?= 4
        , testCase "mixed"             $ displayWidth (u"中a文b")     @?= 6
        ]
    , testGroup "toMaxWidth"
        [ testCase "wider than input passes through"
            $ toMaxWidth 10 "hello"    @?= "hello"
        , testCase "exactly the width passes through"
            $ toMaxWidth 5 "hello"     @?= "hello"
        , testCase "truncate ascii with ellipsis"
            $ toMaxWidth 4 "hello"     @?= "hel" <> u"…"
        , testCase "narrower truncate"
            $ toMaxWidth 2 "hello"     @?= "h"   <> u"…"
        , testCase "width one becomes a lone ellipsis"
            $ toMaxWidth 1 "hello"     @?= u"…"
        , testCase "width zero becomes empty"
            $ toMaxWidth 0 "hello"     @?= ""
        , testCase "wide char truncation respects boundaries"
            -- "中文hi" is 6 columns (2+2+1+1); toMaxWidth 4 keeps the first
            -- wide char plus two ellipses to fill the remaining columns.
            $ toMaxWidth 4 (u"中文hi") @?= u"中……"
        , testCase "wide char gives way to single ellipsis at the boundary"
            -- "中文" is 4 columns; toMaxWidth 3 keeps the first wide char
            -- (2 columns) plus one ellipsis (1 column).
            $ toMaxWidth 3 (u"中文")   @?= u"中…"
        ]
    , testGroup "toWidth"
        [ testCase "pads short ascii"
            $ toWidth 10 "hello"       @?= "hello     "
        , testCase "pad with empty input"
            $ toWidth 4 ""             @?= "    "
        , testCase "exact width unchanged"
            $ toWidth 5 "hello"        @?= "hello"
        , testCase "truncate matches toMaxWidth when over-width"
            $ toWidth 4 "hello"        @?= u"hel…"
        , testCase "pads after a wide-char content too"
            $ toWidth 5 (u"中a")       @?= u"中a  "
        ]
    ]


m :: Maybe Bool -> String -> String -> String -> TestTree
m b tag pat str = testCase tag $ ($ u str) <$> matches (u pat) @?= b