module Main where
import Control.Monad (when)
import System.Exit
import Test.Hspec
import Test.Hspec.Runner
import Test.Helpers
import Test.MemberExpression
import Test.AssignmentAndOperation
import Test.Variables
import Test.If
import Test.Try
import Test.Switch
import Test.Functions
import Test.Classes
import Test.Iteration
import Test.Exports
import Test.Imports
testExpressions :: Spec
testExpressions = describe "Parse literals:" $ do
it "this" $ do
shouldBe (testExpression "this")
"Right LThis"
it "undefined/null" $ do
shouldBe (testExpression "null")
"Right LNull"
it "booleans" $ do
shouldBe (testExpression "true")
"Right (LB True)"
shouldBe (testExpression "false")
"Right (LB False)"
it "ident" $ do
shouldBe (testExpression "test")
"Right (LI \"test\")"
it "numbers" $ do
shouldBe (testExpression "1")
"Right (LN \"1\")"
shouldBe (testExpression "1.10")
"Right (LN \"1.10\")"
shouldBe (testExpression "0.10e3")
"Right (LN \"0.10e3\")"
shouldBe (testExpression "0x11")
"Right (LN \"0x11\")"
shouldBe (testExpression "0b11")
"Right (LN \"0b11\")"
it "strings" $ do
shouldBe (testExpression "\"test\"")
"Right (LS \"test\")"
shouldBe (testExpression "'test'")
"Right (LS \"test\")"
shouldBe (testExpression "'\\''")
"Right (LS \"'\")"
shouldBe (testExpression "'\\n'")
"Right (LS \"\\n\")"
shouldBe (testExpression "'\n'")
"Left \"dummy.js\" (line 1, column 2):\nunexpected \"\\n\"\nexpecting \"\\\\\" or \"'\""
it "template string" $ do
shouldBe (testExpression "`test`")
"Right (LTS [TString \"test\"])"
shouldBe (testExpression "`${\"a\"}`")
"Right (LTS [TExpression (LS \"a\")])"
shouldBe (testExpression "`test ${a + 1} test`")
"Right (LTS [TString \"test \",TExpression (Operation \"+\" (LI \"a\") (LN \"1\")),TString \" test\"])"
shouldBe (testExpression "`${a} test ${b}`")
"Right (LTS [TExpression (LI \"a\"),TString \" test \",TExpression (LI \"b\")])"
it "arrays" $ do
shouldBe (testExpression "[]")
"Right (LA [])"
shouldBe (testExpression "[,]")
"Right (LA [Elision])"
shouldBe (testExpression "[1,2]")
"Right (LA [LN \"1\",LN \"2\"])"
shouldBe (testExpression "[a,2]")
"Right (LA [LI \"a\",LN \"2\"])"
shouldBe (testExpression "[a,...b]")
"Right (LA [LI \"a\",Spread (LI \"b\")])"
shouldBe (testExpression "[a,...[1, 2]]")
"Right (LA [LI \"a\",Spread (LA [LN \"1\",LN \"2\"])])"
shouldBe (testExpression "[a,,b]")
"Right (LA [LI \"a\",Elision,LI \"b\"])"
it "objects" $ do
shouldBe (testExpression "{}")
"Right (LO [])"
shouldBe (testExpression "{a:1}")
"Right (LO [OPKV (LI \"a\") (LN \"1\")])"
shouldBe (testExpression "{b:2,c: \"d\"}")
"Right (LO [OPKV (LI \"b\") (LN \"2\"),OPKV (LI \"c\") (LS \"d\")])"
shouldBe (testExpression "{b:2, c:function() {}}")
"Right (LO [OPKV (LI \"b\") (LN \"2\"),OPKV (LI \"c\") (Function Nothing [] (SBlock []))])"
shouldBe (testExpression "{e}")
"Right (LO [OPI (LI \"e\")])"
shouldBe (testExpression "{e,f:1}")
"Right (LO [OPI (LI \"e\"),OPKV (LI \"f\") (LN \"1\")])"
shouldBe (testExpression "{e,...f}")
"Right (LO [OPI (LI \"e\"),OPI (Spread (LI \"f\"))])"
shouldBe (testExpression "{e,...{a:1}}")
"Right (LO [OPI (LI \"e\"),OPI (Spread (LO [OPKV (LI \"a\") (LN \"1\")]))])"
shouldBe (testExpression "{e,i:...{a:1}}")
"Right (LO [OPI (LI \"e\"),OPKV (LI \"i\") (Spread (LO [OPKV (LI \"a\") (LN \"1\")]))])"
shouldBe (testExpression "{e(){}}")
"Right (LO [OPM (PropertyMethod (LI \"e\") [] (SBlock []))])"
shouldBe (testExpression "{get e(){}}")
"Right (LO [OPM (ClassGetMethod (PropertyMethod (LI \"e\") [] (SBlock [])))])"
shouldBe (testExpression "{set e(){}}")
"Right (LO [OPM (ClassSetMethod (PropertyMethod (LI \"e\") [] (SBlock [])))])"
shouldBe (testExpression "{async e(){}}")
"Right (LO [OPM (Async (PropertyMethod (LI \"e\") [] (SBlock [])))])"
it "regular expression" $ do
shouldBe (testExpression "/test\\/asdf/")
"Right (RegExp \"test\\\\/asdf\" \"\")"
shouldBe (testExpression "/test\\/asdf/gmi")
"Right (RegExp \"test\\\\/asdf\" \"gmi\")"
shouldBe (testExpression "/test\\/asdf/gmi.exec(test)")
"Right (FCall (Dot (RegExp \"test\\\\/asdf\" \"gmi\") (LI \"exec\")) [LI \"test\"])"
it "parens expression" $ do
shouldBe (testExpression "(a,b)")
"Right (LP (Comma (LI \"a\") (LI \"b\")))"
it "new expression" $ testNewExpression
it "function call expression" $ testFunctionCall
it "dotted accesor" $ testDotAccessor
it "array accessor" $ testArrayAccessor
it "function expression" $ testFunctions
it "class expression" $ testClasses
it "unary expression" $ testUnaryOperations
it "assignment expression" $ testAssignments
it "operation expressions" $ testOperations
it "spread expression" $ do
shouldBe (testExpression "{...a}")
"Right (LO [OPI (Spread (LI \"a\"))])"
it "empty expression" $ do
shouldBe (testExpression ";")
"Right Empty"
testStatements = describe "Statements" $ do
it "empty statement" $ do
shouldBe (testStatement ";")
"Right (SExp Empty)"
it "if statement" $ testIf
it "try statement" $ testTry
it "throw statements" $ do
shouldBe (testStatement "throw x;")
"Right (SThrow (LI \"x\"))"
it "variable statements" $ testVariables
it "switch statement" $ testSwitch
it "continue statement" $ do
shouldBe (testStatement "continue")
"Right (SContinue Nothing)"
shouldBe (testStatement "continue x")
"Right (SContinue (Just (LI \"x\")))"
it "debugger statement" $ do
shouldBe (testStatement "debugger")
"Right SDebugger"
it "iteration statement" $ testIteration
it "with statement" $ do
shouldBe (testStatement "with (a) {}")
"Right (SWith (LI \"a\") (SBlock []))"
it "labelled statement" $ do
shouldBe (testStatement "a: x = 1")
"Right (SLabel (LI \"a\") (SExp (Assignment \"=\" (LI \"x\") (LN \"1\"))))"
it "import statement" $ testImports
it "export statement" $ testExports
it "function declaration" $ testFunctionDeclaration
it "class declaration" $ testClassesDeclaration
testAll :: Spec
testAll = do
testExpressions
testStatements
main :: IO ()
main = do
summary <- hspecWithResult defaultConfig testAll
when (summaryFailures summary == 0)
exitSuccess
exitFailure