module Test.Unit where

import Test.Framework
import Test.Framework.Providers.HUnit
import Test.HUnit hiding (Test)
import System.Exit
import System.Directory
import qualified System.FilePath as FilePath
import Language.ECMAScript3.Parser
import Language.ECMAScript3.PrettyPrint
import Language.ECMAScript3.Syntax
import Language.ECMAScript3.Syntax.Annotations
import Language.ECMAScript3.SourceDiff
import Control.Monad
import Data.Default.Class


tests_unit :: Test
tests_unit =
  buildTest $
  do allFiles <- getDirectoryContents testDir
     let validFiles = filter (\x -> FilePath.takeExtension x == ".js") allFiles
     return $ testGroup "Parser Unit tests" $  map genTest validFiles


genTest :: FilePath -> Test
genTest file = testCase file $ parsePrettyTest (testDir `FilePath.combine` file) 

testDir = "test/parse-pretty"

-- | tests the parser with pre-defined test-cases
parsePrettyTest :: FilePath -> Assertion
parsePrettyTest filename =
  readFile filename >>= \src ->
  case parseFromString src of
    Left err -> assertFailure $ "Can't parse a test-case: " ++ filename ++
                                "\nThe error was " ++ (show err)
    Right js -> let str = show $ prettyPrint js
                in  case parseFromString str of
                  Left err ->
                    let msg = "Can't parse pretty-printed code. The error was: "
                              ++ (show err)
                              ++ "\nThe pretty-printed code in question:\n" ++ str
                    in assertFailure msg
                  Right js' -> do
                    let str' = show $ prettyPrint js'
                    unless (str == str') $ do
                      let msg = "The parse of the pretty-printed AST didn't match the original\n"
                                ++ "Diff:\n" ++ jsDiff js js'
                      assertFailure msg
