File: Spec.hs

package info (click to toggle)
haskell-formatting 7.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 224 kB
  • sloc: haskell: 1,514; makefile: 2
file content (226 lines) | stat: -rw-r--r-- 13,655 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS -Wno-type-defaults #-}

import Control.Monad
import Data.Char (isSpace, isUpper)
import Data.Int
import qualified Data.Monoid
import Data.Scientific
import qualified Data.Semigroup
import qualified Data.Text.Lazy as LT
import Data.Time (Day)
import Formatting as F
import Formatting.Time
import Test.Hspec

main :: IO ()
main = hspec spec

spec :: Spec
spec = do
  describe "Regression tests" $ do
    describe "https://github.com/AJChapman/formatting/issues/36" $ do
      it "format (later id <> later id) \"x\"" $ format (later id Data.Monoid.<> later id)    "x" `shouldBe` "xx"
      it "format (later id <> later id) \"x\"" $ format (later id Data.Semigroup.<> later id) "x" `shouldBe` "xx"

    describe "https://github.com/AJChapman/formatting/issues/31" $
      it "10^16-1" $ F.format F.int (10 ^ (16 :: Int) - 1 :: Int) `shouldBe` "9999999999999999"

    describe "https://github.com/AJChapman/formatting/issues/28" $ do
      it "-100"         $ sformat (groupInt 3 ',') (-100 :: Int)       `shouldBe` "-100"
      it "-100,000,000" $ sformat (groupInt 3 ',') (-100000000 :: Int) `shouldBe` "-100,000,000"
      it "100,000,000"  $ sformat (groupInt 3 ',') (100000000 :: Int)  `shouldBe` "100,000,000"

    describe "https://github.com/bos/text-format/issues/18" $ do
      it "build (minBound :: Int)" $ format build (minBound :: Int64) `shouldBe` "-9223372036854775808"
      it "build (maxBound :: Int)" $ format build (maxBound :: Int)   `shouldBe` "9223372036854775807"

    describe "https://github.com/AJChapman/formatting/issues/62" $ do
      it "left 3 '0' (0 :: Int)"  $ format (left 3 '0') (0 ::Int)  `shouldBe` "000"
      it "left 3 '0' (0 :: Word)" $ format (left 3 '0') (0 ::Word) `shouldBe` "000"

    describe "https://github.com/AJChapman/formatting/issues/60" $
      it "build (minBound :: Word)" $ format build (minBound :: Word) `shouldBe` "0"

    describe "https://github.com/AJChapman/formatting/issues/59" $
      it "shortest not scientific" $ format shortest (0.01 :: Double) `shouldBe` "0.01"

  describe "Floating point" $ do
    it "Fixed"    $ format (fixed 4) (12.123456 :: Double) `shouldBe` "12.1235"
    it "Variable" $ format float     (12.123456 :: Double) `shouldBe` "12.123456"
    it "Shortest" $ format shortest  (12.0000 :: Double) `shouldBe` "12"

  describe "Scientific" $ do
    it "sci" $ format sci (scientific 60221409 16) `shouldBe` "6.0221409e23"
    it "scifmt" $ format (scifmt Exponent (Just 3)) (scientific 60221409 16) `shouldBe` "6.022e23"
    it "scifmt" $ format (scifmt Exponent Nothing) (scientific 60221409 16) `shouldBe` "6.0221409e23"
    it "scifmt" $ format (scifmt Fixed Nothing) (scientific 60221409 16) `shouldBe` "602214090000000000000000.0"
    it "scifmt" $ format (scifmt Generic (Just 5)) (scientific 60221409 16) `shouldBe` "6.02214e23"

  describe "Bytes" $ do
    it "1KB" $ format (bytes shortest) (1024 :: Int) `shouldBe` "1KB"
    it "1.15GB" $ format (bytes (fixed 2)) (1234567890 :: Int) `shouldBe` "1.15GB"

  describe
    "Buildable a => Buildable [a]"
    (do it "\"\" :: [Char] (backwards compatibility)"
           (shouldBe (format build ("" :: String)) "")
        it "\"hi\" :: [Char] (backwards compatibility)"
           (shouldBe (format build ("hi" :: String)) "hi")
        it "[1,2,3] :: [Int]"
           (shouldBe (format build ([1,2,3] :: [Int])) "[1,2,3]")
        it "[] :: [Int]"
           (shouldBe (format build ([] :: [Int])) "[]"))

  describe "ords" $ do
      let tests :: [(Int, String)]
          tests = [ ( 1, "1st")
                  , ( 2, "2nd")
                  , ( 3, "3rd")
                  , ( 4, "4th")
                  , ( 5, "5th")
                  , ( 6, "6th")
                  , ( 7, "7th")
                  , ( 8, "8th")
                  , ( 9, "9th")
                  , (10, "10th")
                  , (11, "11th")
                  , (12, "12th")
                  , (13, "13th")
                  , (14, "14th")
                  , (15, "15th")
                  , (16, "16th")
                  , (17, "17th")
                  , (18, "18th")
                  , (19, "19th")
                  , (20, "20th")
                  , (21, "21st")
                  , (22, "22nd")
                  , (23, "23rd")
                  , (24, "24th")
                  , (25, "25th")
                  , (26, "26th")
                  , (27, "27th")
                  , (28, "28th")
                  , (29, "29th")
                  , (30, "30th")
                  , (31, "31st")
                  , (31, "31st")
                  , (32, "32nd")
                  , (33, "33rd")
                  , (34, "34th")
                  ]

      forM_ tests $ \(input, output) -> it output $ format ords input `shouldBe` LT.pack output

  describe "plural" $ do
    let formatPeople = format (int % " " <> plural "person" "people" % ".")
    it "formats a person" $ formatPeople (1 :: Int) `shouldBe` "1 person."
    it "formats a person" $ formatPeople (3 :: Int) `shouldBe` "3 people."

  describe "diffComponents" $ do
    it "59s" $ flip shouldBe "00:00:00:59" $ format diffComponents (59 :: Double)
    it "minute" $ flip shouldBe "00:00:01:00" $ format diffComponents (60 :: Double)
    it "90s" $ flip shouldBe "00:00:01:30" $ format diffComponents (90 :: Double)
    it "hour" $ flip shouldBe "00:01:00:00" $ format diffComponents (3600 :: Double)
    it "day" $ flip shouldBe "01:00:00:00" $ format diffComponents (86400 :: Double)

  describe "container formatters" $ do
    it "maybed Nothing" $ format (maybed "Goodbye" text) Nothing `shouldBe` "Goodbye"
    it "maybed Just" $ format (maybed "Goodbye" text) (Just "Hello") `shouldBe` "Hello"
    it "optioned Nothing" $ format (optioned text) Nothing `shouldBe` ""
    it "optioned Just" $ format (optioned text) (Just "Hello") `shouldBe` "Hello"
    it "eithered Left" $ format (eithered text int) (Left "Error!") `shouldBe` "Error!"
    it "eithered Right" $ format (eithered text int) (Right 69) `shouldBe` "69"
    it "lefted Left" $ format (lefted text) (Left "bingo") `shouldBe` "bingo"
    it "lefted Right" $ format (lefted text) (Right 16) `shouldBe` ""
    it "righted Left" $ format (righted text) (Left 16) `shouldBe` ""
    it "righted Right" $ format (righted text) (Right "bingo") `shouldBe` "bingo"

  describe "list formatters" $ do
    it "concatenated" $ format (concatenated text) ["one", "two", "three"] `shouldBe` "onetwothree"
    it "joinedWith" $ format (joinedWith (mconcat . reverse) int) [123, 456, 789] `shouldBe` "789456123"
    it "intercalated" $ format (intercalated "||" int) [1, 2, 3]  `shouldBe` "1||2||3"
    it "unworded" $ format (unworded int) [1, 2, 3] `shouldBe` "1 2 3"
    it "unlined" $ format (unlined char) ['a'..'c'] `shouldBe` "a\nb\nc\n"
    it "spaced" $ format (spaced int) [1, 2, 3] `shouldBe` "1 2 3"
    it "commaSep" $ format (took 5 (commaSep int)) [1..] `shouldBe` "1,2,3,4,5"
    it "commaSpaceSep" $ format (took 3 (commaSpaceSep ords)) [1..] `shouldBe` "1st, 2nd, 3rd"
    it "list" $ format (list stext) ["one", "two", "three"] `shouldBe` "[one, two, three]"
    it "qlist" $ format (qlist stext) ["one", "two", "three"] `shouldBe` "[\"one\", \"two\", \"three\"]"
    it "took" $ format (took 7 (list bin)) [1..] `shouldBe` "[1, 10, 11, 100, 101, 110, 111]"
    it "dropped" $ format (dropped 3 (list int)) [1..6] `shouldBe` "[4, 5, 6]"

  describe "splitting formatters" $ do
    it "splat" $ format (splat isSpace commaSpaceSep stext) "This\t  is\n\t\t  poorly formatted   " `shouldBe` "This, , , is, , , , , poorly, formatted, , , "
    it "splatWith" $ format (splatWith (LT.chunksOf 3) list int) 1234567890 `shouldBe` "[123, 456, 789, 0]"
    it "splatOn" $ format (splatOn "," unlined text) "one,two,three" `shouldBe` "one\ntwo\nthree\n"
    it "worded" $ format (worded list text) "one  two three  " `shouldBe` "[one, two, three]"
    it "lined" $ format (lined qlist text) "one two three\n\nfour five six\nseven eight nine\n\n" `shouldBe` "[\"one two three\", \"\", \"four five six\", \"seven eight nine\", \"\"]"

  describe "altering combinators" $ do
    it "alteredWith" $ format (alteredWith LT.reverse int) 123456 `shouldBe` "654321"
    it "charsKeptIf" $ format (charsKeptIf isUpper text) "Data.Char.isUpper" `shouldBe` "DCU"
    it "charsRemovedIf" $ format (charsRemovedIf isUpper text) "Data.Char.isUpper" `shouldBe` "ata.har.ispper"
    it "replaced" $ format (replaced "Bruce" "<redacted>" stext) "Bruce replied that Bruce's name was, in fact, '<redacted>'." `shouldBe` "<redacted> replied that <redacted>'s name was, in fact, '<redacted>'."
    it "uppercased" $ format (uppercased text) "I'm not shouting, you're shouting." `shouldBe` "I'M NOT SHOUTING, YOU'RE SHOUTING."
    it "lowercased" $ format (lowercased text) "Cd SrC/; Rm -Rf *" `shouldBe` "cd src/; rm -rf *"
    it "titlecased" $ format (titlecased string) "the life of brian" `shouldBe` "The Life Of Brian"
    it "ltruncated" $ format (ltruncated 5 text) "hellos" `shouldBe` "he..."
    it "ltruncated, non-truncated" $ format (ltruncated 5 text) "hello" `shouldBe` "hello"
    it "rtruncated" $ format (rtruncated 5 text) "hellos" `shouldBe` "...os"
    it "rtruncated, non-truncated" $ format (rtruncated 5 text) "hello" `shouldBe` "hello"
    it "ctruncated" $ format (ctruncated 15 4 text) "The quick brown fox jumps over the lazy dog." `shouldBe` "The quick brown...dog."
    it "ctruncated, non-truncated" $ format (ctruncated 15 4 text) "The quick brown fox" `shouldBe` "The quick brown fox"
    it "lpadded" $ format (lpadded 7 ' ' int) 1 `shouldBe` "      1"
    it "lpadded doesn't shorten" $ format (lpadded 7 ' ' int) 123456789 `shouldBe` "123456789"
    it "rpadded" $ format (rpadded 7 ' ' int) 1 `shouldBe` "1      "
    it "cpadded" $ format (cpadded 7 ' ' int) 1 `shouldBe` "   1   "
    it "lfixed short" $ format (lfixed 10 ' ' int) 123 `shouldBe` "123       "
    it "lfixed at length" $ format (lfixed 10 ' ' int) 1234567890 `shouldBe` "1234567890"
    it "lfixed long" $ format (lfixed 10 ' ' int) 123456789012345 `shouldBe` "1234567..."
    it "rfixed short" $ format (rfixed 10 ' ' int) 123 `shouldBe` "       123"
    it "rfixed at length" $ format (rfixed 10 ' ' int) 1234567890 `shouldBe` "1234567890"
    it "rfixed long" $ format (rfixed 10 ' ' int) 123456789012345 `shouldBe` "...9012345"
    it "cfixed short" $ format (cfixed 4 3 ' ' int) 123 `shouldBe` "    123   "
    it "cfixed at length" $ format (cfixed 4 3 ' ' int) 1234567890 `shouldBe` "1234567890"
    it "cfixed long" $ format (cfixed 4 3 ' ' int) 123456789012345 `shouldBe` "1234...345"

  describe "wrapping combinators" $ do
    it "prefixed" $ format ("The answer is: " % prefixed "wait for it... " int) 42 `shouldBe` "The answer is: wait for it... 42"
    it "prefixed, combining" $ format (unlined (indented 4 (prefixed "- " int))) [1, 2, 3] `shouldBe` "    - 1\n    - 2\n    - 3\n"
    it "suffixed" $ format (suffixed "!!!" int) 7 `shouldBe` "7!!!"
    it "surrounded" $ format (surrounded "***" string) "glue" `shouldBe` "***glue***"
    it "enclosed" $ format (enclosed "<!--" "-->" text) "an html comment" `shouldBe` "<!--an html comment-->"
    it "squoted" $ let obj :: Maybe (Maybe Int); obj = Just Nothing in format ("The object is: " % squoted shown % ".") obj  `shouldBe` "The object is: 'Just Nothing'."
    it "dquoted" $ format ("He said it was based on " % dquoted stext % ".") "science" `shouldBe` "He said it was based on \"science\"."
    it "parenthesised" $ format (took 5 (list (parenthesised int))) [1..] `shouldBe` "[(1), (2), (3), (4), (5)]"
    it "squared" $ format (squared int) 7 `shouldBe` "[7]"
    it "braced" $ format ("\\begin" % braced text) "section" `shouldBe` "\\begin{section}"
    it "angled" $ format (list (angled text)) ["html", "head", "title", "body", "div", "span"] `shouldBe` "[<html>, <head>, <title>, <body>, <div>, <span>]"
    it "backticked" $ format ("Be sure to run" %+ backticked builder %+ "as root.") ":(){:|:&};:" `shouldBe` "Be sure to run `:(){:|:&};:` as root."

  describe "indenters" $ do
    it "indented" $ format (indented 4 int) 7 `shouldBe` "    7"
    it "indentedLines" $ format ("The lucky numbers are:\n" % indentedLines 4 int) [7, 13, 1, 42] `shouldBe` "The lucky numbers are:\n    7\n    13\n    1\n    42\n"
    it "reindented" $ format (reindented 2 text) "one\ntwo\nthree" `shouldBe` "  one\n  two\n  three\n"

  describe "numerical adapters" $ do
    it "roundedTo" $ format (list (roundedTo int)) [10.66, 6.66, 1.0, 3.4] `shouldBe` "[11, 7, 1, 3]"
    it "truncatedTo" $ format (list (truncatedTo int)) [10.66, 6.66, 1.0, 3.4] `shouldBe` "[10, 6, 1, 3]"
    it "ceilingedTo" $ format (list (ceilingedTo int)) [10.66, 6.66, 1.0, 3.4] `shouldBe` "[11, 7, 1, 4]"
    it "flooredTo" $ format (list (flooredTo int)) [10.66, 6.66, 1.0, 3.4] `shouldBe` "[10, 6, 1, 3]"

  describe "structure formatting" $
    it "accessed" $ format (accessed fst int) (1, "hello") `shouldBe` "1"
  -- describe "lens formatters" $ do
  --   it "viewed" $ flip shouldBe "(viewed _1 int) (1, "hello")" $ format

  describe "fixed-width numbers" $ do
    it "binPrefix" $ format (binPrefix 16) 4097 `shouldBe` "0b0001000000000001"
    it "octPrefix" $ format (octPrefix 16) 4097 `shouldBe` "0o0000000000010001"
    it "hexPrefix" $ format (hexPrefix 16) 4097 `shouldBe` "0x0000000000001001"

  describe "mappend with added space (<%+>)" $ do
    let testTime = (read "2022-06-06") :: Day
    it "combines formatters, adding a space" $ format (year <%+> month <%+> dayOfMonth) testTime `shouldBe` "2022 06 06"