packages feed

purescript-0.9.1: tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs

{-# LANGUAGE OverloadedStrings #-}
module Language.PureScript.Ide.Imports.IntegrationSpec where

import           Control.Monad                       (void)
import           Data.Text                           (Text)
import qualified Data.Text                           as T
import qualified Data.Text.IO                        as TIO
import qualified Language.PureScript.Ide.Integration as Integration
import           Test.Hspec

import           System.Directory
import           System.FilePath

setup :: IO ()
setup = do
  Integration.reset
  mapM_ Integration.loadModuleWithDeps ["ImportsSpec", "ImportsSpec1"]

withSupportFiles :: (FilePath -> FilePath -> IO a) -> IO ()
withSupportFiles test = do
  pdir <- Integration.projectDirectory
  let sourceFp = pdir </> "src" </> "ImportsSpec.purs"
      outFp = pdir </> "src" </> "ImportsSpecOut.tmp"
  Integration.deleteFileIfExists outFp
  void $ test sourceFp outFp

outputFileShouldBe :: [Text] -> IO ()
outputFileShouldBe expectation = do
  outFp <- (</> "src" </> "ImportsSpecOut.tmp") <$> Integration.projectDirectory
  outRes <- TIO.readFile outFp
  shouldBe (T.lines outRes) expectation

spec :: Spec
spec = beforeAll_ setup . describe "Adding imports" $ do
  let
    sourceFileSkeleton :: [Text] -> [Text]
    sourceFileSkeleton importSection =
      [ "module ImportsSpec where" , ""] ++ importSection ++ [ "" , "myId = id"]
  it "adds an implicit import" $ do
    withSupportFiles (Integration.addImplicitImport "ImportsSpec1")
    outputFileShouldBe (sourceFileSkeleton
                        [ "import ImportsSpec1"
                        , "import Main (id)"
                        ])
  it "adds an explicit unqualified import" $ do
    withSupportFiles (Integration.addImport "exportedFunction")
    outputFileShouldBe (sourceFileSkeleton
                        [ "import ImportsSpec1 (exportedFunction)"
                        , "import Main (id)"
                        ])
  it "adds an explicit unqualified import (type)" $ do
    withSupportFiles (Integration.addImport "MyType")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyType)"
                                           , "import Main (id)"
                                           ])
  it "adds an explicit unqualified import (parameterized type)" $ do
    withSupportFiles (Integration.addImport "MyParamType")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyParamType)"
                                           , "import Main (id)"
                                           ])
  it "adds an explicit unqualified import (typeclass)" $ do
    withSupportFiles (Integration.addImport "ATypeClass")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (class ATypeClass)"
                                           , "import Main (id)"])
  it "adds an explicit unqualified import (dataconstructor)" $ do
    withSupportFiles (Integration.addImport "MyJust")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyMaybe(MyJust))"
                                           , "import Main (id)"])
  it "adds an explicit unqualified import (newtype)" $ do
    withSupportFiles (Integration.addImport "MyNewtype")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyNewtype(MyNewtype))"
                                           , "import Main (id)"])
  it "adds an explicit unqualified import (typeclass member function)" $ do
    withSupportFiles (Integration.addImport "typeClassFun")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (typeClassFun)"
                                           , "import Main (id)"])
  it "doesn't add a newtypes constructor if only the type is exported" $ do
    withSupportFiles (Integration.addImport "OnlyTypeExported")
    outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (OnlyTypeExported)"
                                            , "import Main (id)"])
  it "doesn't add an import if the identifier is defined in the module itself" $ do
    withSupportFiles (Integration.addImport "myId")
    outputFileShouldBe (sourceFileSkeleton [ "import Main (id)"])
  it "responds with an error if it's undecidable whether we want a type or constructor" $
    withSupportFiles (\sourceFp outFp -> do
                         r <- Integration.addImport "SpecialCase" sourceFp outFp
                         shouldBe False (Integration.resultIsSuccess r)
                         shouldBe False =<< doesFileExist outFp)
  it "responds with an error if the identifier cannot be found and doesn't \
     \write to the output file" $
    withSupportFiles (\sourceFp outFp -> do
                         r <- Integration.addImport "doesntExist" sourceFp outFp
                         shouldBe False (Integration.resultIsSuccess r)
                         shouldBe False =<< doesFileExist outFp)