packages feed

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

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


import           Protolude

import qualified Data.Text                           as T
import qualified Language.PureScript.Ide.Integration as Integration
import           Test.Hspec

import           System.Directory
import           System.FilePath
import           System.IO.UTF8                      (readUTF8FileT)

setup :: IO ()
setup = void (Integration.reset *> Integration.loadAll)

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 <- readUTF8FileT 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 x = x"]
  it "adds an implicit import" $ do
    withSupportFiles (Integration.addImplicitImport "ImportsSpec1")
    outputFileShouldBe (sourceFileSkeleton
                        [ "import ImportsSpec1"
                        ])
  it "adds an explicit unqualified import" $ do
    withSupportFiles (Integration.addImport "exportedFunction")
    outputFileShouldBe (sourceFileSkeleton
                        [ "import ImportsSpec1 (exportedFunction)"
                        ])
  it "adds an explicit unqualified import (type)" $ do
    withSupportFiles (Integration.addImport "MyType")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyType)"])
  it "adds an explicit unqualified import (parameterized type)" $ do
    withSupportFiles (Integration.addImport "MyParamType")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyParamType)"])
  it "adds an explicit unqualified import (typeclass)" $ do
    withSupportFiles (Integration.addImport "ATypeClass")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (class ATypeClass)"])
  it "adds an explicit unqualified import (dataconstructor)" $ do
    withSupportFiles (Integration.addImport "MyJust")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyMaybe(..))"])
  it "adds an explicit unqualified import (newtype)" $ do
    withSupportFiles (Integration.addImport "MyNewtype")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyNewtype(..))"])
  it "adds an explicit unqualified import (typeclass member function)" $ do
    withSupportFiles (Integration.addImport "typeClassFun")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (typeClassFun)"])
  it "doesn't add a newtypes constructor if only the type is exported" $ do
    withSupportFiles (Integration.addImport "OnlyTypeExported")
    outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (OnlyTypeExported)"])
  it "doesn't add an import if the identifier is defined in the module itself" $ do
    withSupportFiles (Integration.addImport "myId")
    outputFileShouldBe (sourceFileSkeleton [])
  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)