{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} -- | Test suite for ACE. module Main where import Control.Applicative import Data.Aeson (Value(..),toJSON,object,(.=)) import qualified Data.Map.Strict as M import Data.Monoid import Data.Text (Text) import Descriptive import qualified Descriptive.Char as Char import qualified Descriptive.Form as Form import qualified Descriptive.Formlet as Formlet import qualified Descriptive.JSON as JSON import qualified Descriptive.Options as Options import Test.Hspec (Spec,it,hspec) import qualified Test.Hspec as Hspec -- | Test suite entry point, returns exit failure if any test fails. main :: IO () main = return () {-hspec spec-} -- | Test suite. spec :: Spec spec = do Hspec.describe "Descriptive.Char" characters Hspec.describe "Descriptive.Form" form Hspec.describe "Descriptive.Formlet" formlet Hspec.describe "Descriptive.JSON" json Hspec.describe "Descriptive.Options" options -------------------------------------------------------------------------------- -- Character parsing tests characters :: Spec characters = do it "describe" (describe (many (Char.char 'k') <> Char.string "abc") mempty == And (Bounded 0 UnlimitedBound (Unit "k")) (Sequence [Unit "a",Unit "b",Unit "c",None])) it "consume" (consume (many (Char.char 'k') <> Char.string "abc") "kkkabc" == (Succeeded "kkkabc")) it "fail generic" (consume (many (Char.char 'k') <> Char.string "abc") "kkkab" == (Failed (Unit "a character"))) it "fail specific" (consume (many (Char.char 'k') <> Char.string "abc") "kkkabj" == (Failed (Unit "c"))) -------------------------------------------------------------------------------- -- Form tests form :: Spec form = do it "basic describe login" (describe ((,) <$> Form.input "username" <*> Form.input "password") mempty == (And (Unit (Form.Input "username")) (Unit (Form.Input "password")))) it "basic describe login" (consume ((,) <$> Form.input "username" <*> Form.input "password") (M.fromList [("username","chrisdone"),("password","god")]) == Succeeded ("chrisdone","god")) it "succeeding login" (consume login (M.fromList [("password2","gob"),("password","gob")]) == Succeeded "gob") it "continuing login" (consume login (M.fromList [("password2","gob"),("password","go")]) == Continued (And (Wrap (Form.Constraint "confirmed password (entered the same twice)") (And (Unit (Form.Input "password")) (Unit (Form.Input "password2")))) (Unit (Form.Input "token")))) it "succeeding disjunction" (consume login (M.fromList [("password2","gob"),("password","go"),("token","woot")]) == Succeeded "woot") where login = Form.validate "confirmed password (entered the same twice)" (\(x,y) -> return (if x == y then Just y else Nothing)) ((,) <$> Form.input "password" <*> Form.input "password2") <|> Form.input "token" -------------------------------------------------------------------------------- -- Formlet tests formlet :: Spec formlet = do it "basic formlet" (describe ((,) <$> Formlet.indexed <*> Formlet.indexed) (Formlet.FormletState mempty 0) == And (Unit (Formlet.Index 0)) (Unit (Formlet.Index 1))) it "succeeding formlet" (consume ((,) <$> Formlet.indexed <*> Formlet.indexed) (Formlet.FormletState (M.fromList [(0,"chrisdone"),(1,"god")]) 0) == Succeeded ("chrisdone","god")) it "succeeding formlet" (consume ((,) <$> Formlet.indexed <*> Formlet.indexed) (Formlet.FormletState (M.fromList [(0,"chrisdone")]) 0) == Failed (Unit (Formlet.Index 1))) -------------------------------------------------------------------------------- -- Options tests options :: Spec options = do it "describe options" (describe server [] == And (And (And (Unit (Options.Constant "start" "cmd")) (Unit (Options.AnyString "SERVER_NAME"))) (Or (Unit (Options.Flag "dev" "Enable dev mode?")) None)) (Unit (Options.Arg "port" "Port to listen on"))) it "succeeding options" (consume server ["start","any","--port","1234","--dev"] == Succeeded ((),"any",True,"1234")) it "succeeding omitting port options" (consume server ["start","any","--port","1234"] == Succeeded ((),"any",False,"1234")) it "failing options" (consume server ["start","any"] == Failed (Unit (Options.Arg "port" "Port to listen on"))) where server = ((,,,) <$> Options.constant "start" "cmd" () <*> Options.anyString "SERVER_NAME" <*> Options.switch "dev" "Enable dev mode?" <*> Options.arg "port" "Port to listen on") -------------------------------------------------------------------------------- -- JSON tests -- | Submit a URL to reddit. data Submission = Submission {submissionToken :: !Integer ,submissionTitle :: !Text ,submissionComment :: !Text ,submissionSubreddit :: !Integer} deriving (Show,Eq) submission :: Monad m => Consumer Value (JSON.Doc Text) m Submission submission = JSON.object "Submission" (Submission <$> JSON.key "token" (JSON.integer "Submission token; see the API docs") <*> JSON.key "title" (JSON.string "Submission title") <*> JSON.key "comment" (JSON.string "Submission comment") <*> JSON.key "subreddit" (JSON.integer "The ID of the subreddit")) sample :: Value sample = toJSON (object ["token" .= 123 ,"title" .= "Some title" ,"comment" .= "This is good" ,"subreddit" .= 234214]) badsample :: Value badsample = toJSON (object ["token" .= 123 ,"title" .= "Some title" ,"comment" .= 123 ,"subreddit" .= 234214]) json :: Spec json = do it "describe JSON" (describe submission (toJSON ()) == Wrap (JSON.Object "Submission") (And (And (And (Wrap (JSON.Key "token") (Unit (JSON.Integer "Submission token; see the API docs"))) (Wrap (JSON.Key "title") (Unit (JSON.Text "Submission title")))) (Wrap (JSON.Key "comment") (Unit (JSON.Text "Submission comment")))) (Wrap (JSON.Key "subreddit") (Unit (JSON.Integer "The ID of the subreddit"))))) it "succeeding json" (consume submission sample == Succeeded (Submission {submissionToken = 123 ,submissionTitle = "Some title" ,submissionComment = "This is good" ,submissionSubreddit = 234214})) it "failing json" (consume submission badsample == Continued (Wrap (JSON.Object "Submission") (Wrap (JSON.Key "comment") (Unit (JSON.Text "Submission comment")))))