packages feed

hmp3-ng-2.19.0: test/WidthSpec.hs

module WidthSpec (tests) where

import Test.Tasty
import Test.Tasty.HUnit

import Data.ByteString (ByteString)
import Data.ByteString.UTF8 qualified as UTF8

import Width (displayWidth, toMaxWidth, toWidth)

-- These tests depend on wcwidth's behaviour 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 "Width"
    [ 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"        @?= "hel" <> u"…"
        , testCase "pads after a wide-char content too"
            $ toWidth 5 (u "中a")      @?= u"中a" <> "  "
        ]
    ]

u :: String -> ByteString
u = UTF8.fromString